Repository: breez/breez-sdk-liquid (language: python)

Issue:
Real-time Sync: Add persistency layer
Closes #501.
Real-time Sync: Add SDK triggers and event loop



Discussion / hints:

Fix patch:
diff --git a/cli/Cargo.lock b/cli/Cargo.lock
index 9b2448d61..699c5a102 100644
--- a/cli/Cargo.lock
+++ b/cli/Cargo.lock
@@ -4,19 +4,13 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.22.0"
+version = "0.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
 dependencies = [
  "gimli",
 ]
 
-[[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
 [[package]]
 name = "adler2"
 version = "2.0.0"
@@ -93,9 +87,9 @@ dependencies = [
 
 [[package]]
 name = "allo-isolate"
-version = "0.1.25"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97b6d794345b06592d0ebeed8e477e41b71e5a0a49df4fc0e4184d5938b99509"
+checksum = "1f67642eb6773fb42a95dd3b348c305ee18dee6642274c6b412d67e985e3befc"
 dependencies = [
  "anyhow",
  "atomic",
@@ -138,9 +132,9 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.15"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -153,47 +147,53 @@ dependencies = [
 
 [[package]]
 name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
 dependencies = [
  "anstyle",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.86"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
 dependencies = [
  "backtrace",
 ]
 
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
 [[package]]
 name = "arrayvec"
 version = "0.7.6"
@@ -212,7 +212,7 @@ dependencies = [
  "nom",
  "num-traits",
  "rusticata-macros",
- "thiserror",
+ "thiserror 1.0.69",
  "time",
 ]
 
@@ -224,7 +224,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
  "synstructure",
 ]
 
@@ -236,14 +236,14 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "async-stream"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
 dependencies = [
  "async-stream-impl",
  "futures-core",
@@ -252,24 +252,24 @@ dependencies = [
 
 [[package]]
 name = "async-stream-impl"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "async-trait"
-version = "0.1.81"
+version = "0.1.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
+checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -297,9 +297,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "axum"
@@ -308,13 +308,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
 dependencies = [
  "async-trait",
- "axum-core",
+ "axum-core 0.3.4",
  "bitflags 1.3.2",
  "bytes",
  "futures-util",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.30",
+ "hyper 0.14.31",
  "itoa",
  "matchit",
  "memchr",
@@ -324,7 +324,34 @@ dependencies = [
  "rustversion",
  "serde",
  "sync_wrapper 0.1.2",
- "tower",
+ "tower 0.4.13",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
+dependencies = [
+ "async-trait",
+ "axum-core 0.4.5",
+ "bytes",
+ "futures-util",
+ "http 1.2.0",
+ "http-body 1.0.1",
+ "http-body-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "sync_wrapper 1.0.2",
+ "tower 0.5.1",
  "tower-layer",
  "tower-service",
 ]
@@ -346,19 +373,39 @@ dependencies = [
  "tower-service",
 ]
 
+[[package]]
+name = "axum-core"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http 1.2.0",
+ "http-body 1.0.1",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "rustversion",
+ "sync_wrapper 1.0.2",
+ "tower-layer",
+ "tower-service",
+]
+
 [[package]]
 name = "backtrace"
-version = "0.3.73"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
 dependencies = [
  "addr2line",
- "cc",
  "cfg-if",
  "libc",
- "miniz_oxide 0.7.4",
+ "miniz_oxide",
  "object",
  "rustc-demangle",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -419,11 +466,11 @@ dependencies = [
 
 [[package]]
 name = "bip39"
-version = "2.0.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
+checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387"
 dependencies = [
- "bitcoin_hashes 0.11.0",
+ "bitcoin_hashes 0.13.0",
  "rand",
  "rand_core",
  "serde",
@@ -472,9 +519,9 @@ dependencies = [
 
 [[package]]
 name = "bitcoin"
-version = "0.32.4"
+version = "0.32.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "788902099d47c8682efe6a7afb01c8d58b9794ba66c06affd81c3d6b560743eb"
+checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026"
 dependencies = [
  "base58ck",
  "bech32 0.11.0",
@@ -652,33 +699,39 @@ dependencies = [
  "bip39",
  "boltz-client",
  "chrono",
+ "ecies",
  "electrum-client",
  "env_logger 0.11.5",
  "flutter_rust_bridge",
  "futures-util",
  "glob",
  "hex",
+ "lazy_static",
  "lightning 0.0.125",
  "log",
  "lwk_common",
  "lwk_signer",
  "lwk_wollet",
  "openssl",
+ "prost 0.13.3",
  "reqwest 0.11.20",
  "rusqlite",
  "rusqlite_migration",
  "sdk-common",
  "security-framework",
  "security-framework-sys",
+ "semver",
  "serde",
  "serde_json",
  "strum",
  "strum_macros",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.69",
  "tokio",
  "tokio-stream",
  "tokio-tungstenite",
+ "tonic 0.12.3",
+ "tonic-build 0.12.3",
  "url",
  "x509-parser",
  "zbase32",
@@ -698,9 +751,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "bytemuck"
-version = "1.18.0"
+version = "1.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
+checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a"
 
 [[package]]
 name = "byteorder"
@@ -710,9 +763,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.7.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
+checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
 
 [[package]]
 name = "cbc"
@@ -725,9 +778,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.1.13"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
+checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc"
 dependencies = [
  "shlex",
 ]
@@ -738,6 +791,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
 [[package]]
 name = "chrono"
 version = "0.4.38"
@@ -774,9 +833,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.16"
+version = "4.5.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019"
+checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -784,9 +843,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.15"
+version = "4.5.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
+checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1"
 dependencies = [
  "anstream",
  "anstyle",
@@ -796,21 +855,21 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.13"
+version = "4.5.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "clap_lex"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
 
 [[package]]
 name = "clipboard-win"
@@ -823,9 +882,9 @@ dependencies = [
 
 [[package]]
 name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
 
 [[package]]
 name = "console_error_panic_hook"
@@ -855,9 +914,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.13"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
 dependencies = [
  "libc",
 ]
@@ -871,6 +930,18 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "critical-section"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
 [[package]]
 name = "crypto-common"
 version = "0.1.6"
@@ -958,7 +1029,7 @@ checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -984,6 +1055,15 @@ dependencies = [
  "powerfmt",
 ]
 
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "digest"
 version = "0.10.7"
@@ -1003,7 +1083,24 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "ecies"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0206e602d2645ec8b24ed8307fadbc6c3110e2b11ab2f806fc02fee49327079"
+dependencies = [
+ "getrandom",
+ "hkdf",
+ "libsecp256k1",
+ "once_cell",
+ "openssl",
+ "parking_lot 0.12.3",
+ "rand_core",
+ "sha2",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -1055,9 +1152,9 @@ dependencies = [
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.34"
+version = "0.8.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
 dependencies = [
  "cfg-if",
 ]
@@ -1122,19 +1219,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "errno"
-version = "0.3.9"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "error-code"
-version = "3.2.0"
+version = "3.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
+checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
 
 [[package]]
 name = "fallible-iterator"
@@ -1150,9 +1247,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
 
 [[package]]
 name = "fastrand"
-version = "2.1.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
 
 [[package]]
 name = "fd-lock"
@@ -1173,12 +1270,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flate2"
-version = "1.0.32"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
 dependencies = [
  "crc32fast",
- "miniz_oxide 0.8.0",
+ "miniz_oxide",
 ]
 
 [[package]]
@@ -1220,7 +1317,7 @@ dependencies = [
  "md-5",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -1255,9 +1352,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1270,9 +1367,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1280,15 +1377,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1297,38 +1394,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
 
 [[package]]
 name = "futures-task"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
 
 [[package]]
 name = "futures-util"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1363,9 +1460,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.15"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -1376,9 +1473,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.29.0"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
 name = "glob"
@@ -1398,7 +1495,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http 0.2.12",
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -1407,17 +1504,17 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
+checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
 dependencies = [
  "atomic-waker",
  "bytes",
  "fnv",
  "futures-core",
  "futures-sink",
- "http 1.1.0",
- "indexmap 2.4.0",
+ "http 1.2.0",
+ "indexmap 2.7.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -1445,6 +1542,12 @@ dependencies = [
  "ahash",
 ]
 
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
 [[package]]
 name = "hashlink"
 version = "0.9.1"
@@ -1508,13 +1611,22 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
 
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
 [[package]]
 name = "hmac"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
 dependencies = [
- "digest",
+ "digest 0.10.7",
 ]
 
 [[package]]
@@ -1539,9 +1651,9 @@ dependencies = [
 
 [[package]]
 name = "http"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
 dependencies = [
  "bytes",
  "fnv",
@@ -1566,7 +1678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
 dependencies = [
  "bytes",
- "http 1.1.0",
+ "http 1.2.0",
 ]
 
 [[package]]
@@ -1577,16 +1689,16 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
 dependencies = [
  "bytes",
  "futures-util",
- "http 1.1.0",
+ "http 1.2.0",
  "http-body 1.0.1",
  "pin-project-lite",
 ]
 
 [[package]]
 name = "httparse"
-version = "1.9.4"
+version = "1.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
 
 [[package]]
 name = "httpdate"
@@ -1611,9 +1723,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "hyper"
-version = "0.14.30"
+version = "0.14.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9"
+checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -1635,17 +1747,18 @@ dependencies = [
 
 [[package]]
 name = "hyper"
-version = "1.4.1"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
+checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
 dependencies = [
  "bytes",
  "futures-channel",
  "futures-util",
- "h2 0.4.6",
- "http 1.1.0",
+ "h2 0.4.7",
+ "http 1.2.0",
  "http-body 1.0.1",
  "httparse",
+ "httpdate",
  "itoa",
  "pin-project-lite",
  "smallvec",
@@ -1655,20 +1768,20 @@ dependencies = [
 
 [[package]]
 name = "hyper-rustls"
-version = "0.27.2"
+version = "0.27.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
+checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
 dependencies = [
  "futures-util",
- "http 1.1.0",
- "hyper 1.4.1",
+ "http 1.2.0",
+ "hyper 1.5.1",
  "hyper-util",
- "rustls 0.23.12",
+ "rustls 0.23.19",
  "rustls-pki-types",
  "tokio",
  "tokio-rustls 0.26.0",
  "tower-service",
- "webpki-roots 0.26.3",
+ "webpki-roots 0.26.7",
 ]
 
 [[package]]
@@ -1677,12 +1790,25 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
 dependencies = [
- "hyper 0.14.30",
+ "hyper 0.14.31",
  "pin-project-lite",
  "tokio",
  "tokio-io-timeout",
 ]
 
+[[package]]
+name = "hyper-timeout"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
+dependencies = [
+ "hyper 1.5.1",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
 [[package]]
 name = "hyper-tls"
 version = "0.5.0"
@@ -1690,7 +1816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
 dependencies = [
  "bytes",
- "hyper 0.14.30",
+ "hyper 0.14.31",
  "native-tls",
  "tokio",
  "tokio-native-tls",
@@ -1698,29 +1824,28 @@ dependencies = [
 
 [[package]]
 name = "hyper-util"
-version = "0.1.7"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
+checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
 dependencies = [
  "bytes",
  "futures-channel",
  "futures-util",
- "http 1.1.0",
+ "http 1.2.0",
  "http-body 1.0.1",
- "hyper 1.4.1",
+ "hyper 1.5.1",
  "pin-project-lite",
  "socket2",
  "tokio",
- "tower",
  "tower-service",
  "tracing",
 ]
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.60"
+version = "0.1.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -1739,6 +1864,124 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -1757,12 +2000,23 @@ dependencies = [
 
 [[package]]
 name = "idna"
-version = "0.5.0"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
 dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
 ]
 
 [[package]]
@@ -1777,12 +2031,12 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.4.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.5",
+ "hashbrown 0.15.2",
 ]
 
 [[package]]
@@ -1806,9 +2060,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.9.0"
+version = "2.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
 
 [[package]]
 name = "is_terminal_polyfill"
@@ -1825,18 +2079,28 @@ dependencies = [
  "either",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
-version = "1.0.11"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
 
 [[package]]
 name = "js-sys"
-version = "0.3.70"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705"
 dependencies = [
+ "once_cell",
  "wasm-bindgen",
 ]
 
@@ -1848,9 +2112,54 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.158"
+version = "0.2.167"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
+
+[[package]]
+name = "libsecp256k1"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1"
+dependencies = [
+ "arrayref",
+ "base64 0.13.1",
+ "digest 0.9.0",
+ "libsecp256k1-core",
+ "libsecp256k1-gen-ecmult",
+ "libsecp256k1-gen-genmult",
+ "rand",
+ "serde",
+]
+
+[[package]]
+name = "libsecp256k1-core"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451"
+dependencies = [
+ "crunchy",
+ "digest 0.9.0",
+ "subtle",
+]
+
+[[package]]
+name = "libsecp256k1-gen-ecmult"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809"
+dependencies = [
+ "libsecp256k1-core",
+]
+
+[[package]]
+name = "libsecp256k1-gen-genmult"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c"
+dependencies = [
+ "libsecp256k1-core",
+]
 
 [[package]]
 name = "libsqlite3-sys"
@@ -1889,7 +2198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "767f388e50251da71f95a3737d6db32c9729f9de6427a54fa92bb994d04d793f"
 dependencies = [
  "bech32 0.9.1",
- "bitcoin 0.32.4",
+ "bitcoin 0.32.5",
  "lightning-invoice 0.32.0",
  "lightning-types",
 ]
@@ -1928,7 +2237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90ab9f6ea77e20e3129235e62a2e6bd64ed932363df104e864ee65ccffb54a8f"
 dependencies = [
  "bech32 0.9.1",
- "bitcoin 0.32.4",
+ "bitcoin 0.32.5",
  "lightning-types",
 ]
 
@@ -1939,7 +2248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1083b8d9137000edf3bfcb1ff011c0d25e0cdd2feb98cc21d6765e64a494148f"
 dependencies = [
  "bech32 0.9.1",
- "bitcoin 0.32.4",
+ "bitcoin 0.32.5",
  "hex-conservative 0.2.1",
 ]
 
@@ -1949,6 +2258,12 @@ version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
+[[package]]
+name = "litemap"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+
 [[package]]
 name = "lock_api"
 version = "0.4.12"
@@ -1977,7 +2292,7 @@ dependencies = [
  "getrandom",
  "qr_code",
  "rand",
- "thiserror",
+ "thiserror 1.0.69",
 ]
 
 [[package]]
@@ -2004,13 +2319,13 @@ dependencies = [
  "lwk_common",
  "lwk_containers",
  "rand",
- "reqwest 0.12.7",
+ "reqwest 0.12.9",
  "serde",
  "serde_bytes",
  "serde_cbor",
  "serde_json",
  "tempfile",
- "thiserror",
+ "thiserror 1.0.69",
  "tracing",
  "wasm-timer",
 ]
@@ -2026,7 +2341,7 @@ dependencies = [
  "elements-miniscript",
  "lwk_common",
  "lwk_jade",
- "thiserror",
+ "thiserror 1.0.69",
 ]
 
 [[package]]
@@ -2046,10 +2361,10 @@ dependencies = [
  "once_cell",
  "rand",
  "regex-lite",
- "reqwest 0.12.7",
+ "reqwest 0.12.9",
  "serde",
  "serde_json",
- "thiserror",
+ "thiserror 1.0.69",
  "tracing",
 ]
 
@@ -2066,7 +2381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
 dependencies = [
  "cfg-if",
- "digest",
+ "digest 0.10.7",
 ]
 
 [[package]]
@@ -2098,15 +2413,6 @@ dependencies = [
  "bitcoin-internals 0.2.0",
 ]
 
-[[package]]
-name = "miniz_oxide"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
-dependencies = [
- "adler",
-]
-
 [[package]]
 name = "miniz_oxide"
 version = "0.8.0"
@@ -2118,11 +2424,10 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
 dependencies = [
- "hermit-abi 0.3.9",
  "libc",
  "wasi",
  "windows-sys 0.52.0",
@@ -2134,6 +2439,12 @@ version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
 
+[[package]]
+name = "multimap"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
+
 [[package]]
 name = "native-tls"
 version = "0.2.12"
@@ -2227,9 +2538,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.36.3"
+version = "0.36.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
+checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
 dependencies = [
  "memchr",
 ]
@@ -2245,9 +2556,13 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+dependencies = [
+ "critical-section",
+ "portable-atomic",
+]
 
 [[package]]
 name = "opaque-debug"
@@ -2257,9 +2572,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
 
 [[package]]
 name = "openssl"
-version = "0.10.66"
+version = "0.10.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
+checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
 dependencies = [
  "bitflags 2.6.0",
  "cfg-if",
@@ -2278,7 +2593,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -2289,18 +2604,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 [[package]]
 name = "openssl-src"
-version = "300.3.1+3.3.1"
+version = "300.4.1+3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91"
+checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.103"
+version = "0.9.104"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
+checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
 dependencies = [
  "cc",
  "libc",
@@ -2387,34 +2702,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
 dependencies = [
  "fixedbitset",
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
 ]
 
 [[package]]
 name = "pin-project"
-version = "1.1.5"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.5"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
 
 [[package]]
 name = "pin-utils"
@@ -2424,9 +2739,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
 
 [[package]]
 name = "polyval"
@@ -2440,6 +2755,12 @@ dependencies = [
  "universal-hash",
 ]
 
+[[package]]
+name = "portable-atomic"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
+
 [[package]]
 name = "powerfmt"
 version = "0.2.0"
@@ -2465,11 +2786,21 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "prettyplease"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.90",
+]
+
 [[package]]
 name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
 dependencies = [
  "unicode-ident",
 ]
@@ -2481,7 +2812,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
 dependencies = [
  "bytes",
- "prost-derive",
+ "prost-derive 0.11.9",
+]
+
+[[package]]
+name = "prost"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f"
+dependencies = [
+ "bytes",
+ "prost-derive 0.13.3",
 ]
 
 [[package]]
@@ -2492,20 +2833,41 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
 dependencies = [
  "bytes",
  "heck 0.4.1",
- "itertools",
+ "itertools 0.10.5",
  "lazy_static",
  "log",
- "multimap",
+ "multimap 0.8.3",
  "petgraph",
- "prettyplease",
- "prost",
- "prost-types",
+ "prettyplease 0.1.25",
+ "prost 0.11.9",
+ "prost-types 0.11.9",
  "regex",
  "syn 1.0.109",
  "tempfile",
  "which",
 ]
 
+[[package]]
+name = "prost-build"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15"
+dependencies = [
+ "bytes",
+ "heck 0.5.0",
+ "itertools 0.13.0",
+ "log",
+ "multimap 0.10.0",
+ "once_cell",
+ "petgraph",
+ "prettyplease 0.2.25",
+ "prost 0.13.3",
+ "prost-types 0.13.3",
+ "regex",
+ "syn 2.0.90",
+ "tempfile",
+]
+
 [[package]]
 name = "prost-derive"
 version = "0.11.9"
@@ -2513,19 +2875,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
 dependencies = [
  "anyhow",
- "itertools",
+ "itertools 0.10.5",
  "proc-macro2",
  "quote",
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "prost-derive"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5"
+dependencies = [
+ "anyhow",
+ "itertools 0.13.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
 [[package]]
 name = "prost-types"
 version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
 dependencies = [
- "prost",
+ "prost 0.11.9",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670"
+dependencies = [
+ "prost 0.13.3",
 ]
 
 [[package]]
@@ -2539,9 +2923,9 @@ dependencies = [
 
 [[package]]
 name = "qrcode-rs"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "312bbb0be6e357c1f8191d3c3b0f892bf2b80240d379d08d92355f1dee6afa74"
+checksum = "e2ead539a9857a2a4e45ec7285812734740c12014cb62e3d1567b1676106afcf"
 
 [[package]]
 name = "querystring"
@@ -2557,57 +2941,61 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
 [[package]]
 name = "quinn"
-version = "0.11.3"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156"
+checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef"
 dependencies = [
  "bytes",
  "pin-project-lite",
  "quinn-proto",
  "quinn-udp",
  "rustc-hash",
- "rustls 0.23.12",
+ "rustls 0.23.19",
  "socket2",
- "thiserror",
+ "thiserror 2.0.4",
  "tokio",
  "tracing",
 ]
 
 [[package]]
 name = "quinn-proto"
-version = "0.11.6"
+version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd"
+checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
 dependencies = [
  "bytes",
+ "getrandom",
  "rand",
  "ring 0.17.8",
  "rustc-hash",
- "rustls 0.23.12",
+ "rustls 0.23.19",
+ "rustls-pki-types",
  "slab",
- "thiserror",
+ "thiserror 2.0.4",
  "tinyvec",
  "tracing",
+ "web-time",
 ]
 
 [[package]]
 name = "quinn-udp"
-version = "0.5.4"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
+checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da"
 dependencies = [
+ "cfg_aliases",
  "libc",
  "once_cell",
  "socket2",
  "tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.36"
+version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
 dependencies = [
  "proc-macro2",
 ]
@@ -2672,9 +3060,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.10.6"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -2684,9 +3072,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.7"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -2701,9 +3089,9 @@ checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
 [[package]]
 name = "reqwest"
@@ -2719,7 +3107,7 @@ dependencies = [
  "h2 0.3.26",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.30",
+ "hyper 0.14.31",
  "hyper-tls",
  "ipnet",
  "js-sys",
@@ -2744,9 +3132,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest"
-version = "0.12.7"
+version = "0.12.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
+checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
 dependencies = [
  "base64 0.22.1",
  "bytes",
@@ -2754,11 +3142,11 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2 0.4.6",
- "http 1.1.0",
+ "h2 0.4.7",
+ "http 1.2.0",
  "http-body 1.0.1",
  "http-body-util",
- "hyper 1.4.1",
+ "hyper 1.5.1",
  "hyper-rustls",
  "hyper-util",
  "ipnet",
@@ -2769,13 +3157,13 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "quinn",
- "rustls 0.23.12",
- "rustls-pemfile 2.1.3",
+ "rustls 0.23.19",
+ "rustls-pemfile 2.2.0",
  "rustls-pki-types",
  "serde",
  "serde_json",
  "serde_urlencoded",
- "sync_wrapper 1.0.1",
+ "sync_wrapper 1.0.2",
  "system-configuration",
  "tokio",
  "tokio-rustls 0.26.0",
@@ -2784,7 +3172,7 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "web-sys",
- "webpki-roots 0.26.3",
+ "webpki-roots 0.26.7",
  "windows-registry",
 ]
 
@@ -2850,9 +3238,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 
 [[package]]
 name = "rustc-hash"
-version = "2.0.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
+checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
 
 [[package]]
 name = "rusticata-macros"
@@ -2865,9 +3253,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.34"
+version = "0.38.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
 dependencies = [
  "bitflags 2.6.0",
  "errno",
@@ -2902,14 +3290,15 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.12"
+version = "0.23.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
+checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
 dependencies = [
+ "log",
  "once_cell",
  "ring 0.17.8",
  "rustls-pki-types",
- "rustls-webpki 0.102.6",
+ "rustls-webpki 0.102.8",
  "subtle",
  "zeroize",
 ]
@@ -2937,19 +3326,21 @@ dependencies = [
 
 [[package]]
 name = "rustls-pemfile"
-version = "2.1.3"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
 dependencies = [
- "base64 0.22.1",
  "rustls-pki-types",
 ]
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.8.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
+checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
+dependencies = [
+ "web-time",
+]
 
 [[package]]
 name = "rustls-webpki"
@@ -2963,9 +3354,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.6"
+version = "0.102.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
 dependencies = [
  "ring 0.17.8",
  "rustls-pki-types",
@@ -2974,9 +3365,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.17"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
 
 [[package]]
 name = "rustyline"
@@ -3009,7 +3400,7 @@ checksum = "e5af959c8bf6af1aff6d2b463a57f71aae53d1332da58419e30ad8dc7011d951"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -3020,11 +3411,11 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
 
 [[package]]
 name = "schannel"
-version = "0.1.23"
+version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
+checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -3059,17 +3450,17 @@ dependencies = [
  "lightning 0.0.118",
  "lightning-invoice 0.26.0",
  "log",
- "prost",
+ "prost 0.11.9",
  "querystring",
  "regex",
  "reqwest 0.11.20",
  "serde",
  "serde_json",
  "strum_macros",
- "thiserror",
+ "thiserror 1.0.69",
  "tokio",
- "tonic",
- "tonic-build",
+ "tonic 0.8.3",
+ "tonic-build 0.8.4",
  "url",
  "urlencoding",
 ]
@@ -3112,7 +3503,7 @@ version = "0.29.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
 dependencies = [
- "bitcoin_hashes 0.13.0",
+ "bitcoin_hashes 0.14.0",
  "secp256k1-sys 0.10.1",
 ]
 
@@ -3196,11 +3587,17 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
 [[package]]
 name = "serde"
-version = "1.0.208"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
 dependencies = [
  "serde_derive",
 ]
@@ -3226,20 +3623,20 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.208"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.125"
+version = "1.0.133"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
 dependencies = [
  "itoa",
  "memchr",
@@ -3289,7 +3686,7 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
 dependencies = [
  "cfg-if",
  "cpufeatures",
- "digest",
+ "digest 0.10.7",
 ]
 
 [[package]]
@@ -3300,7 +3697,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
 dependencies = [
  "cfg-if",
  "cpufeatures",
- "digest",
+ "digest 0.10.7",
 ]
 
 [[package]]
@@ -3335,9 +3732,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "socket2"
-version = "0.5.7"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -3355,6 +3752,12 @@ version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
 [[package]]
 name = "strsim"
 version = "0.10.0"
@@ -3383,7 +3786,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -3405,9 +3808,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.75"
+version = "2.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3422,9 +3825,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
 
 [[package]]
 name = "sync_wrapper"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
 dependencies = [
  "futures-core",
 ]
@@ -3437,14 +3840,14 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "system-configuration"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42"
+checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
 dependencies = [
  "bitflags 2.6.0",
  "core-foundation",
@@ -3463,9 +3866,9 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.12.0"
+version = "3.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
 dependencies = [
  "cfg-if",
  "fastrand",
@@ -3502,22 +3905,42 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.63"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490"
+dependencies = [
+ "thiserror-impl 2.0.4",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.63"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -3531,9 +3954,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.36"
+version = "0.3.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
 dependencies = [
  "deranged",
  "itoa",
@@ -3552,14 +3975,24 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "time-macros"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
 dependencies = [
  "num-conv",
  "time-core",
 ]
 
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
 [[package]]
 name = "tinyvec"
 version = "1.8.0"
@@ -3577,9 +4010,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.39.3"
+version = "1.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
+checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
 dependencies = [
  "backtrace",
  "bytes",
@@ -3611,7 +4044,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
@@ -3641,16 +4074,16 @@ version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
 dependencies = [
- "rustls 0.23.12",
+ "rustls 0.23.19",
  "rustls-pki-types",
  "tokio",
 ]
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
+checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -3674,9 +4107,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.11"
+version = "0.7.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
 dependencies = [
  "bytes",
  "futures-core",
@@ -3693,7 +4126,7 @@ checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb"
 dependencies = [
  "async-stream",
  "async-trait",
- "axum",
+ "axum 0.6.20",
  "base64 0.13.1",
  "bytes",
  "futures-core",
@@ -3701,19 +4134,19 @@ dependencies = [
  "h2 0.3.26",
  "http 0.2.12",
  "http-body 0.4.6",
- "hyper 0.14.30",
- "hyper-timeout",
+ "hyper 0.14.31",
+ "hyper-timeout 0.4.1",
  "percent-encoding",
  "pin-project",
- "prost",
- "prost-derive",
+ "prost 0.11.9",
+ "prost-derive 0.11.9",
  "rustls-native-certs",
  "rustls-pemfile 1.0.4",
  "tokio",
  "tokio-rustls 0.23.4",
  "tokio-stream",
  "tokio-util",
- "tower",
+ "tower 0.4.13",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -3721,19 +4154,66 @@ dependencies = [
  "webpki-roots 0.22.6",
 ]
 
+[[package]]
+name = "tonic"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "axum 0.7.9",
+ "base64 0.22.1",
+ "bytes",
+ "h2 0.4.7",
+ "http 1.2.0",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.5.1",
+ "hyper-timeout 0.5.2",
+ "hyper-util",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.13.3",
+ "rustls-pemfile 2.2.0",
+ "socket2",
+ "tokio",
+ "tokio-rustls 0.26.0",
+ "tokio-stream",
+ "tower 0.4.13",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "webpki-roots 0.26.7",
+]
+
 [[package]]
 name = "tonic-build"
 version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
 dependencies = [
- "prettyplease",
+ "prettyplease 0.1.25",
  "proc-macro2",
- "prost-build",
+ "prost-build 0.11.9",
  "quote",
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "tonic-build"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11"
+dependencies = [
+ "prettyplease 0.2.25",
+ "proc-macro2",
+ "prost-build 0.13.3",
+ "prost-types 0.13.3",
+ "quote",
+ "syn 2.0.90",
+]
+
 [[package]]
 name = "tower"
 version = "0.4.13"
@@ -3754,6 +4234,20 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "tower"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper 0.1.2",
+ "tower-layer",
+ "tower-service",
+]
+
 [[package]]
 name = "tower-layer"
 version = "0.3.3"
@@ -3768,9 +4262,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
 
 [[package]]
 name = "tracing"
-version = "0.1.40"
+version = "0.1.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
 dependencies = [
  "pin-project-lite",
  "tracing-attributes",
@@ -3779,20 +4273,20 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.27"
+version = "0.1.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
 ]
 
 [[package]]
 name = "tracing-core"
-version = "0.1.32"
+version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
 dependencies = [
  "once_cell",
 ]
@@ -3822,13 +4316,13 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http 1.1.0",
+ "http 1.2.0",
  "httparse",
  "log",
  "native-tls",
  "rand",
  "sha1",
- "thiserror",
+ "thiserror 1.0.69",
  "url",
  "utf-8",
 ]
@@ -3841,15 +4335,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.12"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
 
 [[package]]
 name = "unicode-normalization"
@@ -3862,15 +4356,15 @@ dependencies = [
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.11.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
 [[package]]
 name = "universal-hash"
@@ -3896,31 +4390,31 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
 
 [[package]]
 name = "ureq"
-version = "2.8.0"
+version = "2.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3"
+checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.1",
  "flate2",
  "log",
  "native-tls",
  "once_cell",
- "rustls 0.21.12",
- "rustls-webpki 0.101.7",
+ "rustls 0.23.19",
+ "rustls-pki-types",
  "serde",
  "serde_json",
  "url",
- "webpki-roots 0.25.4",
+ "webpki-roots 0.26.7",
 ]
 
 [[package]]
 name = "url"
-version = "2.5.2"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
 dependencies = [
  "form_urlencoded",
- "idna 0.5.0",
+ "idna 1.0.3",
  "percent-encoding",
 ]
 
@@ -3936,6 +4430,18 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
 [[package]]
 name = "utf8parse"
 version = "0.2.2"
@@ -3971,9 +4477,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.93"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -3982,36 +4488,37 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.93"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.43"
+version = "0.4.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
+checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d"
 dependencies = [
  "cfg-if",
  "js-sys",
+ "once_cell",
  "wasm-bindgen",
  "web-sys",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.93"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -4019,22 +4526,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.93"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.93"
+version = "0.2.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49"
 
 [[package]]
 name = "wasm-timer"
@@ -4053,9 +4560,19 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.70"
+version = "0.3.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "web-time"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -4088,9 +4605,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
 
 [[package]]
 name = "webpki-roots"
-version = "0.26.3"
+version = "0.26.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd"
+checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
 dependencies = [
  "rustls-pki-types",
 ]
@@ -4335,6 +4852,18 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
 [[package]]
 name = "x509-parser"
 version = "0.16.0"
@@ -4348,10 +4877,34 @@ dependencies = [
  "nom",
  "oid-registry",
  "rusticata-macros",
- "thiserror",
+ "thiserror 1.0.69",
  "time",
 ]
 
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+ "synstructure",
+]
+
 [[package]]
 name = "zbase32"
 version = "0.1.2"
@@ -4376,7 +4929,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.90",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+ "synstructure",
 ]
 
 [[package]]
@@ -4384,3 +4958,25 @@ name = "zeroize"
 version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
diff --git a/lib/Cargo.lock b/lib/Cargo.lock
index 67f83b082..dc97051b0 100644
--- a/lib/Cargo.lock
+++ b/lib/Cargo.lock
@@ -4283,6 +4283,7 @@ dependencies = [
  "tower-layer",
  "tower-service",
  "tracing",
+ "webpki-roots 0.26.5",
 ]
 
 [[package]]
diff --git a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h
index e17d67b3b..5da740029 100644
--- a/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h
+++ b/lib/bindings/langs/flutter/breez_sdk_liquid/include/breez_sdk_liquid.h
@@ -494,6 +494,7 @@ typedef struct wire_cst_config {
   int32_t network;
   uint64_t payment_timeout_sec;
   uint32_t zero_conf_min_fee_rate_msat;
+  struct wire_cst_list_prim_u_8_strict *sync_service_url;
   uint64_t *zero_conf_max_amount_sat;
   struct wire_cst_list_prim_u_8_strict *breez_api_key;
 } wire_cst_config;
diff --git a/lib/bindings/src/breez_sdk_liquid.udl b/lib/bindings/src/breez_sdk_liquid.udl
index 9513c60a6..ada8a2ca8 100644
--- a/lib/bindings/src/breez_sdk_liquid.udl
+++ b/lib/bindings/src/breez_sdk_liquid.udl
@@ -332,6 +332,7 @@ dictionary Config {
     LiquidNetwork network;
     u64 payment_timeout_sec;
     u32 zero_conf_min_fee_rate_msat;
+    string sync_service_url;
     string? breez_api_key;
     string? cache_dir;
     u64? zero_conf_max_amount_sat;
@@ -563,6 +564,7 @@ enum PaymentState {
     "TimedOut",
     "Refundable",
     "RefundPending",
+    "Recoverable",
 };
 
 dictionary RefundableSwap {
@@ -668,6 +670,12 @@ callback interface Signer {
 
     [Throws=SignerError]
     sequence<u8> hmac_sha256(sequence<u8> msg, string derivation_path);
+
+    [Throws=SignerError]
+    sequence<u8> ecies_encrypt(sequence<u8> msg);
+
+    [Throws=SignerError]
+    sequence<u8> ecies_decrypt(sequence<u8> msg);
 };
 
 interface BindingLiquidSdk {
diff --git a/lib/core/Cargo.toml b/lib/core/Cargo.toml
index a44e35ace..5e049a6d5 100644
--- a/lib/core/Cargo.toml
+++ b/lib/core/Cargo.toml
@@ -51,11 +51,11 @@ electrum-client = { version = "0.19.0" }
 zbase32 = "0.1.2"
 x509-parser = { version = "0.16.0" }
 tempfile = "3"
-tonic = { version = "0.12.3", features = ["tls"] }
 prost = "0.13.3"
 ecies = "0.2.7"
 semver = "1.0.23"
 lazy_static = "1.5.0"
+tonic = { version = "0.12.3", features = ["tls", "tls-webpki-roots"] }
 
 [dev-dependencies]
 paste = "1.0.15"
diff --git a/lib/core/build.rs b/lib/core/build.rs
index 37bc80270..d93dbcb0e 100644
--- a/lib/core/build.rs
+++ b/lib/core/build.rs
@@ -1,6 +1,8 @@
 use anyhow::*;
 use glob::glob;
 use std::env;
+use std::os::unix::process::CommandExt as _;
+use std::process::Command;
 use std::result::Result::Ok;
 
 /// Adds a temporary workaround for an issue with the Rust compiler and Android
@@ -35,8 +37,13 @@ fn setup_x86_64_android_workaround() {
 fn compile_protos() -> Result<()> {
     tonic_build::configure()
         .build_server(false)
-        .out_dir("./src/sync/model")
+        .out_dir("src/sync/model")
         .compile_protos(&["src/sync/proto/sync.proto"], &["src/sync/proto"])?;
+    Command::new("rustfmt")
+        .arg("--edition")
+        .arg("2021")
+        .arg("src/sync/model/sync.rs")
+        .exec();
     Ok(())
 }
 
diff --git a/lib/core/src/chain_swap.rs b/lib/core/src/chain_swap.rs
index e9aacd62b..b5d4468a6 100644
--- a/lib/core/src/chain_swap.rs
+++ b/lib/core/src/chain_swap.rs
@@ -111,6 +111,23 @@ impl ChainSwapHandler {
             .fetch_chain_swap_by_id(id)?
             .ok_or(anyhow!("No ongoing Chain Swap found for ID {id}"))?;
 
+        if let Some(sync_state) = self.persister.get_sync_state_by_data_id(&swap.id)? {
+            if !sync_state.is_local {
+                let status = &update.status;
+                let swap_state = ChainSwapStates::from_str(status)
+                    .map_err(|_| anyhow!("Invalid ChainSwapState for Chain Swap {id}: {status}"))?;
+
+                match swap_state {
+                    // If the swap is not local (pulled from real-time sync) we do not claim twice
+                    ChainSwapStates::TransactionServerMempool
+                    | ChainSwapStates::TransactionServerConfirmed => {
+                        return Ok(());
+                    }
+                    _ => {}
+                }
+            }
+        }
+
         match swap.direction {
             Direction::Incoming => self.on_new_incoming_status(&swap, update).await,
             Direction::Outgoing => self.on_new_outgoing_status(&swap, update).await,
@@ -1132,6 +1149,11 @@ impl ChainSwapHandler {
         to_state: PaymentState,
     ) -> Result<(), PaymentError> {
         match (from_state, to_state) {
+            (Recoverable, Pending | Refundable | RefundPending | Failed | Complete) => Ok(()),
+            (_, Recoverable) => Err(PaymentError::Generic {
+                err: format!("Cannot transition from {from_state:?} to Recoverable state"),
+            }),
+
             (_, Created) => Err(PaymentError::Generic {
                 err: "Cannot transition to Created state".to_string(),
             }),
@@ -1356,10 +1378,7 @@ impl ChainSwapHandler {
 
 #[cfg(test)]
 mod tests {
-    use std::{
-        collections::{HashMap, HashSet},
-        sync::Arc,
-    };
+    use std::collections::{HashMap, HashSet};
 
     use anyhow::Result;
 
@@ -1370,16 +1389,15 @@ mod tests {
         },
         test_utils::{
             chain_swap::{new_chain_swap, new_chain_swap_handler},
-            persist::new_persister,
+            persist::create_persister,
         },
     };
 
     #[tokio::test]
     async fn test_chain_swap_state_transitions() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
-        let storage = Arc::new(storage);
+        create_persister!(persister);
 
-        let chain_swap_handler = new_chain_swap_handler(storage.clone())?;
+        let chain_swap_handler = new_chain_swap_handler(persister.clone())?;
 
         // Test valid combinations of states
         let all_states = HashSet::from([Created, Pending, Complete, TimedOut, Failed]);
@@ -1403,7 +1421,7 @@ mod tests {
             for allowed_state in allowed_states {
                 let chain_swap =
                     new_chain_swap(Direction::Incoming, Some(*first_state), false, None);
-                storage.insert_chain_swap(&chain_swap)?;
+                persister.insert_chain_swap(&chain_swap)?;
 
                 assert!(chain_swap_handler
                     .update_swap_info(&chain_swap.id, *allowed_state, None, None, None, None)
@@ -1427,7 +1445,7 @@ mod tests {
             for disallowed_state in disallowed_states {
                 let chain_swap =
                     new_chain_swap(Direction::Incoming, Some(*first_state), false, None);
-                storage.insert_chain_swap(&chain_swap)?;
+                persister.insert_chain_swap(&chain_swap)?;
 
                 assert!(chain_swap_handler
                     .update_swap_info(&chain_swap.id, *disallowed_state, None, None, None, None)
diff --git a/lib/core/src/frb_generated.rs b/lib/core/src/frb_generated.rs
index 6084b6853..e4fdda9bf 100644
--- a/lib/core/src/frb_generated.rs
+++ b/lib/core/src/frb_generated.rs
@@ -2063,6 +2063,7 @@ impl CstDecode<crate::model::PaymentState> for i32 {
             4 => crate::model::PaymentState::TimedOut,
             5 => crate::model::PaymentState::Refundable,
             6 => crate::model::PaymentState::RefundPending,
+            7 => crate::model::PaymentState::Recoverable,
             _ => unreachable!("Invalid variant for PaymentState: {}", self),
         }
     }
@@ -2343,6 +2344,7 @@ impl SseDecode for crate::model::Config {
         let mut var_network = <crate::model::LiquidNetwork>::sse_decode(deserializer);
         let mut var_paymentTimeoutSec = <u64>::sse_decode(deserializer);
         let mut var_zeroConfMinFeeRateMsat = <u32>::sse_decode(deserializer);
+        let mut var_syncServiceUrl = <String>::sse_decode(deserializer);
         let mut var_zeroConfMaxAmountSat = <Option<u64>>::sse_decode(deserializer);
         let mut var_breezApiKey = <Option<String>>::sse_decode(deserializer);
         return crate::model::Config {
@@ -2354,6 +2356,7 @@ impl SseDecode for crate::model::Config {
             network: var_network,
             payment_timeout_sec: var_paymentTimeoutSec,
             zero_conf_min_fee_rate_msat: var_zeroConfMinFeeRateMsat,
+            sync_service_url: var_syncServiceUrl,
             zero_conf_max_amount_sat: var_zeroConfMaxAmountSat,
             breez_api_key: var_breezApiKey,
         };
@@ -3627,6 +3630,7 @@ impl SseDecode for crate::model::PaymentState {
             4 => crate::model::PaymentState::TimedOut,
             5 => crate::model::PaymentState::Refundable,
             6 => crate::model::PaymentState::RefundPending,
+            7 => crate::model::PaymentState::Recoverable,
             _ => unreachable!("Invalid variant for PaymentState: {}", inner),
         };
     }
@@ -4506,6 +4510,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::Config {
             self.zero_conf_min_fee_rate_msat
                 .into_into_dart()
                 .into_dart(),
+            self.sync_service_url.into_into_dart().into_dart(),
             self.zero_conf_max_amount_sat.into_into_dart().into_dart(),
             self.breez_api_key.into_into_dart().into_dart(),
         ]
@@ -5617,6 +5622,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::PaymentState {
             Self::TimedOut => 4.into_dart(),
             Self::Refundable => 5.into_dart(),
             Self::RefundPending => 6.into_dart(),
+            Self::Recoverable => 7.into_dart(),
             _ => unreachable!(),
         }
     }
@@ -6555,6 +6561,7 @@ impl SseEncode for crate::model::Config {
         <crate::model::LiquidNetwork>::sse_encode(self.network, serializer);
         <u64>::sse_encode(self.payment_timeout_sec, serializer);
         <u32>::sse_encode(self.zero_conf_min_fee_rate_msat, serializer);
+        <String>::sse_encode(self.sync_service_url, serializer);
         <Option<u64>>::sse_encode(self.zero_conf_max_amount_sat, serializer);
         <Option<String>>::sse_encode(self.breez_api_key, serializer);
     }
@@ -7584,6 +7591,7 @@ impl SseEncode for crate::model::PaymentState {
                 crate::model::PaymentState::TimedOut => 4,
                 crate::model::PaymentState::Refundable => 5,
                 crate::model::PaymentState::RefundPending => 6,
+                crate::model::PaymentState::Recoverable => 7,
                 _ => {
                     unimplemented!("");
                 }
@@ -8599,6 +8607,7 @@ mod io {
                 network: self.network.cst_decode(),
                 payment_timeout_sec: self.payment_timeout_sec.cst_decode(),
                 zero_conf_min_fee_rate_msat: self.zero_conf_min_fee_rate_msat.cst_decode(),
+                sync_service_url: self.sync_service_url.cst_decode(),
                 zero_conf_max_amount_sat: self.zero_conf_max_amount_sat.cst_decode(),
                 breez_api_key: self.breez_api_key.cst_decode(),
             }
@@ -10029,6 +10038,7 @@ mod io {
                 network: Default::default(),
                 payment_timeout_sec: Default::default(),
                 zero_conf_min_fee_rate_msat: Default::default(),
+                sync_service_url: core::ptr::null_mut(),
                 zero_conf_max_amount_sat: core::ptr::null_mut(),
                 breez_api_key: core::ptr::null_mut(),
             }
@@ -12027,6 +12037,7 @@ mod io {
         network: i32,
         payment_timeout_sec: u64,
         zero_conf_min_fee_rate_msat: u32,
+        sync_service_url: *mut wire_cst_list_prim_u_8_strict,
         zero_conf_max_amount_sat: *mut u64,
         breez_api_key: *mut wire_cst_list_prim_u_8_strict,
     }
diff --git a/lib/core/src/model.rs b/lib/core/src/model.rs
index b67e8dead..49ddf8950 100644
--- a/lib/core/src/model.rs
+++ b/lib/core/src/model.rs
@@ -28,6 +28,7 @@ use crate::utils;
 // Both use f64 for the maximum precision when converting between units
 pub const STANDARD_FEE_RATE_SAT_PER_VBYTE: f64 = 0.1;
 pub const LOWBALL_FEE_RATE_SAT_PER_VBYTE: f64 = 0.01;
+const BREEZ_SYNC_SERVICE_URL: &str = "https://datasync.breez.technology";
 
 /// Configuration for the Liquid SDK
 #[derive(Clone, Debug, Serialize)]
@@ -47,6 +48,8 @@ pub struct Config {
     pub payment_timeout_sec: u64,
     /// Zero-conf minimum accepted fee-rate in millisatoshis per vbyte
     pub zero_conf_min_fee_rate_msat: u32,
+    /// The url of the real-time sync service
+    pub sync_service_url: String,
     /// Maximum amount in satoshi to accept zero-conf payments with
     /// Defaults to [crate::receive_swap::DEFAULT_ZERO_CONF_MAX_SAT]
     pub zero_conf_max_amount_sat: Option<u64>,
@@ -65,6 +68,7 @@ impl Config {
             network: LiquidNetwork::Mainnet,
             payment_timeout_sec: 15,
             zero_conf_min_fee_rate_msat: DEFAULT_ZERO_CONF_MIN_FEE_RATE_MAINNET,
+            sync_service_url: BREEZ_SYNC_SERVICE_URL.to_string(),
             zero_conf_max_amount_sat: None,
             breez_api_key: Some(breez_api_key),
         }
@@ -80,6 +84,7 @@ impl Config {
             network: LiquidNetwork::Testnet,
             payment_timeout_sec: 15,
             zero_conf_min_fee_rate_msat: DEFAULT_ZERO_CONF_MIN_FEE_RATE_TESTNET,
+            sync_service_url: BREEZ_SYNC_SERVICE_URL.to_string(),
             zero_conf_max_amount_sat: None,
             breez_api_key,
         }
@@ -259,10 +264,10 @@ pub trait Signer: Send + Sync {
     fn hmac_sha256(&self, msg: Vec<u8>, derivation_path: String) -> Result<Vec<u8>, SignerError>;
 
     /// Encrypts a message using (ECIES)[ecies::encrypt]
-    fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;
+    fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError>;
 
     /// Decrypts a message using (ECIES)[ecies::decrypt]
-    fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError>;
+    fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError>;
 }
 
 /// An argument when calling [crate::sdk::LiquidSdk::connect].
@@ -1013,6 +1018,12 @@ pub enum PaymentState {
     ///
     /// When the refund tx is broadcast, `refund_tx_id` is set in the swap.
     RefundPending = 6,
+
+    /// ## Recoverable Swaps
+    ///
+    /// The status for swaps that have been synced in, and whose information is recoverable from
+    /// chain
+    Recoverable = 7,
 }
 impl ToSql for PaymentState {
     fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
@@ -1030,6 +1041,7 @@ impl FromSql for PaymentState {
                 4 => Ok(PaymentState::TimedOut),
                 5 => Ok(PaymentState::Refundable),
                 6 => Ok(PaymentState::RefundPending),
+                7 => Ok(PaymentState::Recoverable),
                 _ => Err(FromSqlError::OutOfRange(i)),
             },
             _ => Err(FromSqlError::InvalidType),
diff --git a/lib/core/src/persist/address.rs b/lib/core/src/persist/address.rs
index 4e66b51d1..933ba0463 100644
--- a/lib/core/src/persist/address.rs
+++ b/lib/core/src/persist/address.rs
@@ -101,11 +101,11 @@ impl Persister {
 mod tests {
     use anyhow::Result;
 
-    use crate::test_utils::persist::new_persister;
+    use crate::test_utils::persist::create_persister;
 
     #[test]
     fn test_next_expired_reserved_address() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
         let address = "tlq1pq2amlulhea6ltq7x3eu9atsc2nnrer7yt7xve363zxedqwu2mk6ctcyv9awl8xf28cythreqklt5q0qqwsxzlm6wu4z6d574adl9zh2zmr0h85gt534n";
 
         storage.insert_or_update_reserved_address(address, 100)?;
@@ -131,7 +131,7 @@ mod tests {
 
     #[test]
     fn test_delete_reserved_address() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
         let address = "tlq1pq2amlulhea6ltq7x3eu9atsc2nnrer7yt7xve363zxedqwu2mk6ctcyv9awl8xf28cythreqklt5q0qqwsxzlm6wu4z6d574adl9zh2zmr0h85gt534n";
 
         storage.insert_or_update_reserved_address(address, 100)?;
diff --git a/lib/core/src/persist/backup.rs b/lib/core/src/persist/backup.rs
index 344567900..db33d5acd 100644
--- a/lib/core/src/persist/backup.rs
+++ b/lib/core/src/persist/backup.rs
@@ -40,12 +40,12 @@ mod tests {
 
     use crate::{
         model::PaymentState,
-        test_utils::persist::{new_persister, new_receive_swap, new_send_swap},
+        test_utils::persist::{create_persister, new_receive_swap, new_send_swap},
     };
 
     #[test]
     fn test_backup_and_restore() -> Result<()> {
-        let (_local_temp_dir, local) = new_persister()?;
+        create_persister!(local);
 
         local.insert_send_swap(&new_send_swap(Some(PaymentState::Pending)))?;
         local.insert_receive_swap(&new_receive_swap(Some(PaymentState::Pending)))?;
@@ -55,7 +55,7 @@ mod tests {
         local.backup(backup_path.clone())?;
         assert!(backup_path.exists());
 
-        let (_remote_temp_dir, remote) = new_persister()?;
+        create_persister!(remote);
 
         remote.restore_from_backup(backup_path)?;
         assert_eq!(remote.list_ongoing_swaps()?.len(), 2);
diff --git a/lib/core/src/persist/cache.rs b/lib/core/src/persist/cache.rs
index 085cf334b..88e9ca324 100644
--- a/lib/core/src/persist/cache.rs
+++ b/lib/core/src/persist/cache.rs
@@ -128,11 +128,11 @@ impl Persister {
 mod tests {
     use anyhow::Result;
 
-    use crate::test_utils::persist::new_persister;
+    use crate::test_utils::persist::create_persister;
 
     #[test]
     fn test_cached_items() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
+        create_persister!(persister);
 
         persister.update_cached_item("key1", "val1".to_string())?;
         let item_value = persister.get_cached_item("key1")?;
@@ -147,7 +147,7 @@ mod tests {
 
     #[test]
     fn test_get_last_derivation_index() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
+        create_persister!(persister);
 
         let maybe_last_index = persister.get_last_derivation_index()?;
         assert!(maybe_last_index.is_none());
@@ -169,7 +169,7 @@ mod tests {
 
     #[test]
     fn test_next_derivation_index() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
+        create_persister!(persister);
 
         let maybe_next_index = persister.next_derivation_index()?;
         assert!(maybe_next_index.is_none());
diff --git a/lib/core/src/persist/chain.rs b/lib/core/src/persist/chain.rs
index a9b5143ee..9be65cffe 100644
--- a/lib/core/src/persist/chain.rs
+++ b/lib/core/src/persist/chain.rs
@@ -6,11 +6,11 @@ use rusqlite::{named_params, params, Connection, Row, TransactionBehavior};
 use sdk_common::bitcoin::hashes::{hex::ToHex, sha256, Hash};
 use serde::{Deserialize, Serialize};
 
+use crate::ensure_sdk;
 use crate::error::PaymentError;
 use crate::model::*;
 use crate::persist::{get_where_clause_state_in, Persister};
 use crate::sync::model::RecordType;
-use crate::{ensure_sdk, get_updated_fields};
 
 impl Persister {
     pub(crate) fn insert_chain_swap(&self, chain_swap: &ChainSwap) -> Result<()> {
@@ -81,9 +81,9 @@ impl Persister {
             },
         )?;
 
-        Self::commit_outgoing(&tx, &chain_swap.id, RecordType::Chain, None)?;
-
+        self.commit_outgoing(&tx, &chain_swap.id, RecordType::Chain, None)?;
         tx.commit()?;
+        self.sync_trigger.try_send(())?;
 
         Ok(())
     }
@@ -254,8 +254,10 @@ impl Persister {
         swap_id: &str,
         accept_zero_conf: bool,
     ) -> Result<(), PaymentError> {
-        let con: Connection = self.get_connection()?;
-        con.execute(
+        let mut con: Connection = self.get_connection()?;
+        let tx = con.transaction_with_behavior(TransactionBehavior::Immediate)?;
+
+        tx.execute(
             "UPDATE chain_swaps
             SET
                 accept_zero_conf = :accept_zero_conf
@@ -266,6 +268,19 @@ impl Persister {
                 ":accept_zero_conf": accept_zero_conf,
             },
         )?;
+        self.commit_outgoing(
+            &tx,
+            swap_id,
+            RecordType::Chain,
+            Some(vec!["accept_zero_conf".to_string()]),
+        )?;
+        tx.commit()?;
+        self.sync_trigger
+            .try_send(())
+            .map_err(|err| PaymentError::Generic {
+                err: format!("Could not trigger manual sync: {err:?}"),
+            })?;
+
         Ok(())
     }
 
@@ -368,9 +383,6 @@ impl Persister {
             },
         )?;
 
-        let updated_fields = get_updated_fields!(server_lockup_tx_id);
-        Self::commit_outgoing(&tx, swap_id, RecordType::Chain, updated_fields)?;
-
         tx.commit()?;
 
         Ok(())
diff --git a/lib/core/src/persist/mod.rs b/lib/core/src/persist/mod.rs
index d783a0859..c0886e63c 100644
--- a/lib/core/src/persist/mod.rs
+++ b/lib/core/src/persist/mod.rs
@@ -18,12 +18,14 @@ use anyhow::{anyhow, Result};
 use migrations::current_migrations;
 use rusqlite::{params, params_from_iter, Connection, OptionalExtension, Row, ToSql};
 use rusqlite_migration::{Migrations, M};
+use tokio::sync::mpsc::Sender;
 
 const DEFAULT_DB_FILENAME: &str = "storage.sql";
 
 pub(crate) struct Persister {
     main_db_dir: PathBuf,
     network: LiquidNetwork,
+    sync_trigger: Sender<()>,
 }
 
 /// Builds a WHERE clause that checks if `state` is any of the given arguments
@@ -39,7 +41,11 @@ fn get_where_clause_state_in(allowed_states: &[PaymentState]) -> String {
 }
 
 impl Persister {
-    pub fn new(working_dir: &str, network: LiquidNetwork) -> Result<Self> {
+    pub fn new(
+        working_dir: &str,
+        network: LiquidNetwork,
+        sync_trigger: Sender<()>,
+    ) -> Result<Self> {
         let main_db_dir = PathBuf::from_str(working_dir)?;
         if !main_db_dir.exists() {
             create_dir_all(&main_db_dir)?;
@@ -47,6 +53,7 @@ impl Persister {
         Ok(Persister {
             main_db_dir,
             network,
+            sync_trigger,
         })
     }
 
@@ -533,7 +540,7 @@ mod tests {
     use crate::{
         prelude::ListPaymentsRequest,
         test_utils::persist::{
-            new_payment_tx_data, new_persister, new_receive_swap, new_send_swap,
+            create_persister, new_payment_tx_data, new_receive_swap, new_send_swap,
         },
     };
 
@@ -541,7 +548,7 @@ mod tests {
 
     #[test]
     fn test_get_payments() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         let payment_tx_data = new_payment_tx_data(PaymentType::Send);
         storage.insert_or_update_payment(
@@ -563,7 +570,7 @@ mod tests {
 
     #[test]
     fn test_list_ongoing_swaps() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         storage.insert_send_swap(&new_send_swap(None))?;
         storage.insert_receive_swap(&new_receive_swap(Some(PaymentState::Pending)))?;
diff --git a/lib/core/src/persist/receive.rs b/lib/core/src/persist/receive.rs
index 8d04b0d27..b237db9e3 100644
--- a/lib/core/src/persist/receive.rs
+++ b/lib/core/src/persist/receive.rs
@@ -6,11 +6,11 @@ use rusqlite::{named_params, params, Connection, Row, TransactionBehavior};
 use sdk_common::bitcoin::hashes::{hex::ToHex, sha256, Hash};
 use serde::{Deserialize, Serialize};
 
+use crate::ensure_sdk;
 use crate::error::PaymentError;
 use crate::model::*;
 use crate::persist::{get_where_clause_state_in, Persister};
 use crate::sync::model::RecordType;
-use crate::{ensure_sdk, get_updated_fields};
 
 impl Persister {
     pub(crate) fn insert_receive_swap(&self, receive_swap: &ReceiveSwap) -> Result<()> {
@@ -71,9 +71,9 @@ impl Persister {
             },
         )?;
 
-        Self::commit_outgoing(&tx, &receive_swap.id, RecordType::Receive, None)?;
-
+        self.commit_outgoing(&tx, &receive_swap.id, RecordType::Receive, None)?;
         tx.commit()?;
+        self.sync_trigger.try_send(())?;
 
         Ok(())
     }
@@ -327,6 +327,11 @@ impl Persister {
         // NOTE: Receive currently does not update any fields, bypassing the commit logic for now
         // let updated_fields = None;
         // Self::commit_outgoing(&tx, swap_id, RecordType::Receive, updated_fields)?;
+        // self.sync_trigger
+        //     .try_send(())
+        //     .map_err(|err| PaymentError::Generic {
+        //         err: format!("Could not trigger manual sync: {err:?}"),
+        //     })?;
 
         tx.commit()?;
 
@@ -376,13 +381,13 @@ impl InternalCreateReverseResponse {
 mod tests {
     use anyhow::{anyhow, Result};
 
-    use crate::test_utils::persist::{new_persister, new_receive_swap};
+    use crate::test_utils::persist::{create_persister, new_receive_swap};
 
     use super::PaymentState;
 
     #[test]
     fn test_fetch_receive_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         let receive_swap = new_receive_swap(None);
 
@@ -399,7 +404,7 @@ mod tests {
 
     #[test]
     fn test_list_receive_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         // List general receive swaps
         let range = 0..3;
@@ -425,7 +430,7 @@ mod tests {
 
     #[test]
     fn test_update_receive_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         let receive_swap = new_receive_swap(None);
         storage.insert_receive_swap(&receive_swap)?;
diff --git a/lib/core/src/persist/send.rs b/lib/core/src/persist/send.rs
index 99ecb6dc1..4a2f11178 100644
--- a/lib/core/src/persist/send.rs
+++ b/lib/core/src/persist/send.rs
@@ -55,9 +55,9 @@ impl Persister {
             ),
         )?;
 
-        Self::commit_outgoing(&tx, &send_swap.id, RecordType::Send, None)?;
-
+        self.commit_outgoing(&tx, &send_swap.id, RecordType::Send, None)?;
         tx.commit()?;
+        self.sync_trigger.try_send(())?;
 
         Ok(())
     }
@@ -250,9 +250,13 @@ impl Persister {
         )?;
 
         let updated_fields = get_updated_fields!(preimage);
-        Self::commit_outgoing(&tx, swap_id, RecordType::Send, updated_fields)?;
-
+        self.commit_outgoing(&tx, swap_id, RecordType::Send, updated_fields)?;
         tx.commit()?;
+        self.sync_trigger
+            .try_send(())
+            .map_err(|err| PaymentError::Generic {
+                err: format!("Could not trigger manual sync: {err:?}"),
+            })?;
 
         Ok(())
     }
@@ -345,13 +349,13 @@ impl InternalCreateSubmarineResponse {
 mod tests {
     use anyhow::{anyhow, Result};
 
-    use crate::test_utils::persist::{new_persister, new_send_swap};
+    use crate::test_utils::persist::{create_persister, new_send_swap};
 
     use super::PaymentState;
 
     #[test]
     fn test_fetch_send_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
         let send_swap = new_send_swap(None);
 
         storage.insert_send_swap(&send_swap)?;
@@ -367,7 +371,7 @@ mod tests {
 
     #[test]
     fn test_list_send_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         // List general send swaps
         let range = 0..3;
@@ -393,7 +397,7 @@ mod tests {
 
     #[test]
     fn test_update_send_swap() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
+        create_persister!(storage);
 
         let mut send_swap = new_send_swap(None);
         storage.insert_send_swap(&send_swap)?;
diff --git a/lib/core/src/persist/sync.rs b/lib/core/src/persist/sync.rs
index f80e20dec..f53ddad2d 100644
--- a/lib/core/src/persist/sync.rs
+++ b/lib/core/src/persist/sync.rs
@@ -1,7 +1,9 @@
 use std::collections::HashMap;
 
 use anyhow::Result;
-use rusqlite::{named_params, Connection, OptionalExtension, Row, Statement, TransactionBehavior};
+use rusqlite::{
+    named_params, Connection, OptionalExtension, Row, Statement, Transaction, TransactionBehavior,
+};
 
 use super::{PaymentState, Persister};
 use crate::{
@@ -242,7 +244,8 @@ impl Persister {
     }
 
     pub(crate) fn commit_outgoing(
-        con: &Connection,
+        &self,
+        tx: &Transaction,
         data_id: &str,
         record_type: RecordType,
         updated_fields: Option<Vec<String>>,
@@ -261,7 +264,7 @@ impl Persister {
                 )")
             })
             .unwrap_or("NULL".to_string());
-        con.execute(&format!("
+        tx.execute(&format!("
             INSERT OR REPLACE INTO sync_outgoing(record_id, data_id, record_type, commit_time, updated_fields_json)
             VALUES(
                 :record_id, 
@@ -476,7 +479,7 @@ impl Persister {
                         :description,
                         :state
                     )",
-                    [params, &[(":state", &PaymentState::Created)]]
+                    [params, &[(":state", &PaymentState::Recoverable)]]
                         .concat()
                         .as_slice(),
                 )?;
@@ -569,7 +572,7 @@ impl Persister {
                         :description,
                         :state
                     )",
-                    [params, &[(":state", &PaymentState::Created)]]
+                    [params, &[(":state", &PaymentState::Recoverable)]]
                         .concat()
                         .as_slice(),
                 )?;
@@ -681,7 +684,7 @@ impl Persister {
                         :server_lockup_tx_id,
                         :state
                     )",
-                    [params, &[(":state", &PaymentState::Created)]]
+                    [params, &[(":state", &PaymentState::Recoverable)]]
                         .concat()
                         .as_slice(),
                 )?;
diff --git a/lib/core/src/receive_swap.rs b/lib/core/src/receive_swap.rs
index b3edf66dc..730befc9e 100644
--- a/lib/core/src/receive_swap.rs
+++ b/lib/core/src/receive_swap.rs
@@ -9,9 +9,7 @@ use lwk_wollet::hashes::hex::DisplayHex;
 use tokio::sync::{broadcast, Mutex};
 
 use crate::chain::liquid::LiquidChainService;
-use crate::model::PaymentState::{
-    Complete, Created, Failed, Pending, RefundPending, Refundable, TimedOut,
-};
+use crate::model::PaymentState::*;
 use crate::model::{Config, PaymentTxData, PaymentType, ReceiveSwap};
 use crate::prelude::{Swap, Transaction};
 use crate::{ensure_sdk, utils};
@@ -61,7 +59,9 @@ impl ReceiveSwapHandler {
     /// Handles status updates from Boltz for Receive swaps
     pub(crate) async fn on_new_status(&self, update: &boltz::Update) -> Result<()> {
         let id = &update.id;
-        let swap_state = &update.status;
+        let status = &update.status;
+        let swap_state = RevSwapStates::from_str(status)
+            .map_err(|_| anyhow!("Invalid RevSwapState for Receive Swap {id}: {status}"))?;
         let receive_swap = self
             .persister
             .fetch_receive_swap_by_id(id)?
@@ -69,13 +69,23 @@ impl ReceiveSwapHandler {
 
         info!("Handling Receive Swap transition to {swap_state:?} for swap {id}");
 
-        match RevSwapStates::from_str(swap_state) {
-            Ok(
-                RevSwapStates::SwapExpired
-                | RevSwapStates::InvoiceExpired
-                | RevSwapStates::TransactionFailed
-                | RevSwapStates::TransactionRefunded,
-            ) => {
+        if let Some(sync_state) = self.persister.get_sync_state_by_data_id(&receive_swap.id)? {
+            if !sync_state.is_local {
+                match swap_state {
+                    // If the swap is not local (pulled from real-time sync) we do not claim twice
+                    RevSwapStates::TransactionMempool | RevSwapStates::TransactionConfirmed => {
+                        return Ok(())
+                    }
+                    _ => {}
+                }
+            }
+        }
+
+        match swap_state {
+            RevSwapStates::SwapExpired
+            | RevSwapStates::InvoiceExpired
+            | RevSwapStates::TransactionFailed
+            | RevSwapStates::TransactionRefunded => {
                 match receive_swap.mrh_tx_id {
                     Some(mrh_tx_id) => {
                         warn!("Swap {id} is expired but MRH payment was received: txid {mrh_tx_id}")
@@ -90,7 +100,7 @@ impl ReceiveSwapHandler {
             }
             // The lockup tx is in the mempool and we accept 0-conf => try to claim
             // Execute 0-conf preconditions check
-            Ok(RevSwapStates::TransactionMempool) => {
+            RevSwapStates::TransactionMempool => {
                 let Some(transaction) = update.transaction.clone() else {
                     return Err(anyhow!("Unexpected payload from Boltz status stream"));
                 };
@@ -173,7 +183,7 @@ impl ReceiveSwapHandler {
 
                 Ok(())
             }
-            Ok(RevSwapStates::TransactionConfirmed) => {
+            RevSwapStates::TransactionConfirmed => {
                 let Some(transaction) = update.transaction.clone() else {
                     return Err(anyhow!("Unexpected payload from Boltz status stream"));
                 };
@@ -219,14 +229,10 @@ impl ReceiveSwapHandler {
                 Ok(())
             }
 
-            Ok(_) => {
-                debug!("Unhandled state for Receive Swap {id}: {swap_state}");
+            _ => {
+                debug!("Unhandled state for Receive Swap {id}: {swap_state:?}");
                 Ok(())
             }
-
-            _ => Err(anyhow!(
-                "Invalid RevSwapState for Receive Swap {id}: {swap_state}"
-            )),
         }
     }
 
@@ -364,6 +370,11 @@ impl ReceiveSwapHandler {
         to_state: PaymentState,
     ) -> Result<(), PaymentError> {
         match (from_state, to_state) {
+            (Recoverable, Pending | Refundable | RefundPending | Failed | Complete) => Ok(()),
+            (_, Recoverable) => Err(PaymentError::Generic {
+                err: format!("Cannot transition from {from_state:?} to Recoverable state"),
+            }),
+
             (_, Created) => Err(PaymentError::Generic {
                 err: "Cannot transition to Created state".to_string(),
             }),
@@ -428,27 +439,23 @@ impl ReceiveSwapHandler {
 
 #[cfg(test)]
 mod tests {
-    use std::{
-        collections::{HashMap, HashSet},
-        sync::Arc,
-    };
+    use std::collections::{HashMap, HashSet};
 
     use anyhow::Result;
 
     use crate::{
         model::PaymentState::{self, *},
         test_utils::{
-            persist::{new_persister, new_receive_swap},
+            persist::{create_persister, new_receive_swap},
             receive_swap::new_receive_swap_handler,
         },
     };
 
     #[tokio::test]
     async fn test_receive_swap_state_transitions() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
-        let storage = Arc::new(storage);
+        create_persister!(persister);
 
-        let receive_swap_state_handler = new_receive_swap_handler(storage.clone())?;
+        let receive_swap_state_handler = new_receive_swap_handler(persister.clone())?;
 
         // Test valid combinations of states
         let valid_combinations = HashMap::from([
@@ -467,7 +474,7 @@ mod tests {
         for (first_state, allowed_states) in valid_combinations.iter() {
             for allowed_state in allowed_states {
                 let receive_swap = new_receive_swap(Some(*first_state));
-                storage.insert_receive_swap(&receive_swap)?;
+                persister.insert_receive_swap(&receive_swap)?;
 
                 assert!(receive_swap_state_handler
                     .update_swap_info(&receive_swap.id, *allowed_state, None, None, None, None)
@@ -491,7 +498,7 @@ mod tests {
         for (first_state, disallowed_states) in invalid_combinations.iter() {
             for disallowed_state in disallowed_states {
                 let receive_swap = new_receive_swap(Some(*first_state));
-                storage.insert_receive_swap(&receive_swap)?;
+                persister.insert_receive_swap(&receive_swap)?;
 
                 assert!(receive_swap_state_handler
                     .update_swap_info(&receive_swap.id, *disallowed_state, None, None, None, None)
diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs
index d65e44017..85ef01bd2 100644
--- a/lib/core/src/sdk.rs
+++ b/lib/core/src/sdk.rs
@@ -49,6 +49,9 @@ use crate::{
 use ::lightning::offers::invoice::Bolt12Invoice;
 use ::lightning::offers::offer::Offer;
 
+use self::sync::client::BreezSyncerClient;
+use self::sync::SyncService;
+
 pub const DEFAULT_DATA_DIR: &str = ".data";
 /// Number of blocks to monitor a swap after its timeout block height
 pub const CHAIN_SWAP_MONITORING_PERIOD_BITCOIN_BLOCKS: u32 = 4320;
@@ -70,6 +73,7 @@ pub struct LiquidSdk {
     pub(crate) shutdown_sender: watch::Sender<()>,
     pub(crate) shutdown_receiver: watch::Receiver<()>,
     pub(crate) send_swap_handler: SendSwapHandler,
+    pub(crate) sync_service: Arc<SyncService>,
     pub(crate) receive_swap_handler: ReceiveSwapHandler,
     pub(crate) chain_swap_handler: Arc<ChainSwapHandler>,
     pub(crate) buy_bitcoin_service: Arc<dyn BuyBitcoinApi>,
@@ -162,9 +166,23 @@ impl LiquidSdk {
             &fingerprint_hex,
         )?;
 
-        let persister = Arc::new(Persister::new(&working_dir, config.network)?);
+        let (sync_trigger_tx, sync_trigger_rx) = tokio::sync::mpsc::channel::<()>(30);
+        let persister = Arc::new(Persister::new(
+            &working_dir,
+            config.network,
+            sync_trigger_tx,
+        )?);
         persister.init()?;
 
+        let syncer_client = Box::new(BreezSyncerClient::new());
+        let sync_service = Arc::new(SyncService::new(
+            config.sync_service_url.clone(),
+            persister.clone(),
+            signer.clone(),
+            syncer_client,
+            sync_trigger_rx,
+        ));
+
         let onchain_wallet = Arc::new(LiquidOnchainWallet::new(
             config.clone(),
             &cache_dir,
@@ -233,6 +251,7 @@ impl LiquidSdk {
             shutdown_receiver,
             send_swap_handler,
             receive_swap_handler,
+            sync_service,
             chain_swap_handler,
             buy_bitcoin_service,
         });
@@ -294,6 +313,10 @@ impl LiquidSdk {
             .clone()
             .start(self.shutdown_receiver.clone())
             .await;
+        self.sync_service
+            .clone()
+            .start(self.shutdown_receiver.clone())
+            .await?;
         self.track_swap_updates().await;
         self.track_pending_swaps().await;
 
@@ -539,12 +562,12 @@ impl LiquidSdk {
                         None => pending_send_sat += p.amount_sat,
                     },
                     Created => pending_send_sat += p.amount_sat,
-                    Refundable | RefundPending | TimedOut => {}
+                    Refundable | RefundPending | TimedOut | Recoverable => {}
                 },
                 PaymentType::Receive => match p.status {
                     Complete => confirmed_received_sat += p.amount_sat,
                     Pending => pending_receive_sat += p.amount_sat,
-                    Created | Refundable | RefundPending | Failed | TimedOut => {}
+                    Created | Refundable | RefundPending | Failed | TimedOut | Recoverable => {}
                 },
             }
         }
@@ -881,6 +904,12 @@ impl LiquidSdk {
                 };
             }
             Ok(InputType::Bolt11 { invoice }) => {
+                self.sync_service
+                    .pull()
+                    .await
+                    .map_err(|err| PaymentError::Generic {
+                        err: format!("Could not pull real-time sync changes: {err:?}"),
+                    })?;
                 self.ensure_send_is_not_self_transfer(&invoice.bolt11)?;
                 self.validate_bolt11_invoice(&invoice.bolt11)?;
 
@@ -1212,7 +1241,7 @@ impl LiquidSdk {
                 }
                 Pending => return Err(PaymentError::PaymentInProgress),
                 Complete => return Err(PaymentError::AlreadyPaid),
-                RefundPending | Refundable | Failed => {
+                RefundPending | Refundable | Failed | Recoverable => {
                     return Err(PaymentError::invalid_invoice(
                         "Payment has already failed. Please try with another invoice",
                     ))
@@ -2771,7 +2800,7 @@ mod tests {
         test_utils::{
             chain::{MockBitcoinChainService, MockHistory, MockLiquidChainService},
             chain_swap::{new_chain_swap, TEST_BITCOIN_TX},
-            persist::{new_persister, new_receive_swap, new_send_swap},
+            persist::{create_persister, new_receive_swap, new_send_swap},
             sdk::{new_liquid_sdk, new_liquid_sdk_with_chain_services},
             status_stream::MockStatusStream,
             swapper::MockSwapper,
@@ -2876,8 +2905,7 @@ mod tests {
 
     #[tokio::test]
     async fn test_receive_swap_update_tracking() -> Result<()> {
-        let (_tmp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
+        create_persister!(persister);
         let swapper = Arc::new(MockSwapper::default());
         let status_stream = Arc::new(MockStatusStream::new());
 
@@ -2943,8 +2971,7 @@ mod tests {
 
     #[tokio::test]
     async fn test_send_swap_update_tracking() -> Result<()> {
-        let (_tmp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
+        create_persister!(persister);
         let swapper = Arc::new(MockSwapper::default());
         let status_stream = Arc::new(MockStatusStream::new());
 
@@ -3000,8 +3027,7 @@ mod tests {
 
     #[tokio::test]
     async fn test_chain_swap_update_tracking() -> Result<()> {
-        let (_tmp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
+        create_persister!(persister);
         let swapper = Arc::new(MockSwapper::default());
         let status_stream = Arc::new(MockStatusStream::new());
         let liquid_chain_service = Arc::new(Mutex::new(MockLiquidChainService::new()));
diff --git a/lib/core/src/send_swap.rs b/lib/core/src/send_swap.rs
index f152ca384..f6d370bab 100644
--- a/lib/core/src/send_swap.rs
+++ b/lib/core/src/send_swap.rs
@@ -61,7 +61,9 @@ impl SendSwapHandler {
     /// Handles status updates from Boltz for Send swaps
     pub(crate) async fn on_new_status(&self, update: &boltz::Update) -> Result<()> {
         let id = &update.id;
-        let swap_state = &update.status;
+        let status = &update.status;
+        let swap_state = SubSwapStates::from_str(status)
+            .map_err(|_| anyhow!("Invalid SubSwapState for Send Swap {id}: {status}"))?;
         let swap = self
             .persister
             .fetch_send_swap_by_id(id)?
@@ -70,16 +72,16 @@ impl SendSwapHandler {
         info!("Handling Send Swap transition to {swap_state:?} for swap {id}");
 
         // See https://docs.boltz.exchange/v/api/lifecycle#normal-submarine-swaps
-        match SubSwapStates::from_str(swap_state) {
+        match swap_state {
             // Boltz has locked the HTLC
-            Ok(SubSwapStates::InvoiceSet) => {
+            SubSwapStates::InvoiceSet => {
                 warn!("Received `invoice.set` state for Send Swap {id}");
                 Ok(())
             }
 
             // Boltz has detected the lockup in the mempool, we can speed up
             // the claim by doing so cooperatively
-            Ok(SubSwapStates::TransactionClaimPending) => {
+            SubSwapStates::TransactionClaimPending => {
                 self.cooperate_claim(&swap).await.map_err(|e| {
                     error!("Could not cooperate Send Swap {id} claim: {e}");
                     anyhow!("Could not post claim details. Err: {e:?}")
@@ -89,7 +91,7 @@ impl SendSwapHandler {
             }
 
             // Boltz announced they successfully broadcast the (cooperative or non-cooperative) claim tx
-            Ok(SubSwapStates::TransactionClaimed) => {
+            SubSwapStates::TransactionClaimed => {
                 debug!("Send Swap {id} has been claimed");
 
                 match swap.preimage {
@@ -118,11 +120,9 @@ impl SendSwapHandler {
             // 2. The swap has expired (>24h)
             // 3. Lockup failed (we sent too little funds)
             // We initiate a cooperative refund, and then fallback to a regular one
-            Ok(
-                SubSwapStates::TransactionLockupFailed
-                | SubSwapStates::InvoiceFailedToPay
-                | SubSwapStates::SwapExpired,
-            ) => {
+            SubSwapStates::TransactionLockupFailed
+            | SubSwapStates::InvoiceFailedToPay
+            | SubSwapStates::SwapExpired => {
                 match swap.lockup_tx_id {
                     Some(_) => match swap.refund_tx_id {
                         Some(refund_tx_id) => warn!(
@@ -161,14 +161,10 @@ impl SendSwapHandler {
                 Ok(())
             }
 
-            Ok(_) => {
-                debug!("Unhandled state for Send Swap {id}: {swap_state}");
+            _ => {
+                debug!("Unhandled state for Send Swap {id}: {swap_state:?}");
                 Ok(())
             }
-
-            _ => Err(anyhow!(
-                "Invalid SubSwapState for Send Swap {id}: {swap_state}"
-            )),
         }
     }
 
@@ -500,6 +496,11 @@ impl SendSwapHandler {
         to_state: PaymentState,
     ) -> Result<(), PaymentError> {
         match (from_state, to_state) {
+            (Recoverable, Pending | Refundable | RefundPending | Failed | Complete) => Ok(()),
+            (_, Recoverable) => Err(PaymentError::Generic {
+                err: format!("Cannot transition from {from_state:?} to Recoverable state"),
+            }),
+
             (TimedOut, Created) => Ok(()),
             (_, Created) => Err(PaymentError::Generic {
                 err: "Cannot transition from {from_state:?} to Created state".to_string(),
@@ -551,25 +552,21 @@ impl SendSwapHandler {
 
 #[cfg(test)]
 mod tests {
-    use std::{
-        collections::{HashMap, HashSet},
-        sync::Arc,
-    };
+    use std::collections::{HashMap, HashSet};
 
     use anyhow::Result;
 
     use crate::{
         model::PaymentState::{self, *},
         test_utils::{
-            persist::{new_persister, new_send_swap},
+            persist::{create_persister, new_send_swap},
             send_swap::new_send_swap_handler,
         },
     };
 
     #[tokio::test]
     async fn test_send_swap_state_transitions() -> Result<()> {
-        let (_temp_dir, storage) = new_persister()?;
-        let storage = Arc::new(storage);
+        create_persister!(storage);
         let send_swap_handler = new_send_swap_handler(storage.clone())?;
 
         // Test valid combinations of states
diff --git a/lib/core/src/signer.rs b/lib/core/src/signer.rs
index 1746bf4c5..8b58909b2 100644
--- a/lib/core/src/signer.rs
+++ b/lib/core/src/signer.rs
@@ -254,23 +254,19 @@ impl Signer for SdkSigner {
             .to_vec())
     }
 
-    fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
+    fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
         let keypair = self.xprv.to_keypair(&self.secp);
         let rc_pub = keypair.public_key().to_public_key().to_bytes();
-        Ok(
-            ecies::encrypt(&rc_pub, msg).map_err(|err| SignerError::Generic {
-                err: format!("Could not encrypt data: {err}"),
-            })?,
-        )
+        ecies::encrypt(&rc_pub, &msg).map_err(|err| SignerError::Generic {
+            err: format!("Could not encrypt data: {err}"),
+        })
     }
 
-    fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
+    fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
         let rc_prv = self.xprv.to_priv().to_bytes();
-        Ok(
-            ecies::decrypt(&rc_prv, msg).map_err(|err| SignerError::Generic {
-                err: format!("Could not decrypt data: {err}"),
-            })?,
-        )
+        ecies::decrypt(&rc_prv, &msg).map_err(|err| SignerError::Generic {
+            err: format!("Could not decrypt data: {err}"),
+        })
     }
 }
 
diff --git a/lib/core/src/sync/mod.rs b/lib/core/src/sync/mod.rs
index a0710db87..126159b48 100644
--- a/lib/core/src/sync/mod.rs
+++ b/lib/core/src/sync/mod.rs
@@ -4,7 +4,8 @@ use std::time::Duration;
 
 use anyhow::{anyhow, Result};
 use futures_util::TryFutureExt;
-use tokio::sync::watch;
+use tokio::sync::mpsc::Receiver;
+use tokio::sync::{watch, Mutex};
 
 use crate::sync::model::sync::{Record, SetRecordRequest, SetRecordStatus};
 use crate::utils;
@@ -26,6 +27,7 @@ pub(crate) struct SyncService {
     persister: Arc<Persister>,
     signer: Arc<Box<dyn Signer>>,
     client: Box<dyn SyncerClient>,
+    sync_trigger: Mutex<Receiver<()>>,
 }
 
 impl SyncService {
@@ -34,12 +36,15 @@ impl SyncService {
         persister: Arc<Persister>,
         signer: Arc<Box<dyn Signer>>,
         client: Box<dyn SyncerClient>,
+        sync_trigger: Receiver<()>,
     ) -> Self {
+        let sync_trigger = Mutex::new(sync_trigger);
         Self {
             remote_url,
             persister,
             signer,
             client,
+            sync_trigger,
         }
     }
 
@@ -55,20 +60,32 @@ impl SyncService {
         }
     }
 
-    pub(crate) async fn run(self: Arc<Self>, mut shutdown: watch::Receiver<()>) -> Result<()> {
-        self.client.connect(self.remote_url.clone()).await?;
-
-        self.check_remote_change()?;
+    async fn run_event_loop(&self) {
+        if let Err(err) = self.pull().and_then(|_| self.push()).await {
+            log::debug!("Could not run sync event loop: {err:?}");
+        }
+    }
 
+    pub(crate) async fn start(self: Arc<Self>, mut shutdown: watch::Receiver<()>) -> Result<()> {
         tokio::spawn(async move {
+            if let Err(err) = self.client.connect(self.remote_url.clone()).await {
+                log::warn!("Could not connect to sync service: {err:?}");
+                return;
+            }
+            if let Err(err) = self.check_remote_change() {
+                log::warn!("Could not check for remote change: {err:?}");
+                return;
+            }
+
+            let mut sync_trigger = self.sync_trigger.lock().await;
             let mut event_loop_interval = tokio::time::interval(Duration::from_secs(30));
 
             loop {
                 tokio::select! {
-                    _ = event_loop_interval.tick() => {
-                        if let Err(err) = self.pull().and_then(|_| self.push()).await {
-                            log::debug!("Could not run sync event loop: {err:?}");
-                        }
+                    _ = event_loop_interval.tick() => self.run_event_loop().await,
+                    Some(_) = sync_trigger.recv() => {
+                        self.run_event_loop().await;
+                        event_loop_interval.reset();
                     }
                     _ = shutdown.changed() => {
                         log::info!("Received shutdown signal, exiting realtime sync service loop");
@@ -232,7 +249,7 @@ impl SyncService {
         Ok(())
     }
 
-    async fn pull(&self) -> Result<()> {
+    pub(crate) async fn pull(&self) -> Result<()> {
         // Step 1: Fetch and save incoming records from remote, then update local tip
         self.fetch_and_save_records().await?;
 
@@ -332,7 +349,6 @@ impl SyncService {
 mod tests {
     use anyhow::{anyhow, Result};
     use std::{collections::HashMap, sync::Arc};
-    use tokio::sync::{mpsc, Mutex};
 
     use crate::{
         persist::Persister,
@@ -340,24 +356,19 @@ mod tests {
         sync::model::SyncState,
         test_utils::{
             chain_swap::new_chain_swap,
-            persist::{new_persister, new_receive_swap, new_send_swap},
+            persist::{create_persister, new_receive_swap, new_send_swap},
             sync::{
-                new_chain_sync_data, new_receive_sync_data, new_send_sync_data, MockSyncerClient,
+                new_chain_sync_data, new_receive_sync_data, new_send_sync_data, new_sync_service,
             },
             wallet::MockSigner,
         },
     };
 
-    use super::{
-        model::{data::SyncData, sync::Record, RecordType},
-        SyncService,
-    };
+    use super::model::{data::SyncData, sync::Record, RecordType};
 
     #[tokio::test]
     async fn test_incoming_sync_create_and_update() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
-
+        create_persister!(persister);
         let signer: Arc<Box<dyn Signer>> = Arc::new(Box::new(MockSigner::new()));
 
         let sync_data = vec![
@@ -371,31 +382,28 @@ mod tests {
             Record::new(sync_data[2].clone(), 3, signer.clone())?,
         ];
 
-        let (incoming_tx, incoming_rx) = mpsc::channel::<Record>(10);
-        let outgoing_records = Arc::new(Mutex::new(HashMap::new()));
-        let client = Box::new(MockSyncerClient::new(incoming_rx, outgoing_records.clone()));
-        let sync_service =
-            SyncService::new("".to_string(), persister.clone(), signer.clone(), client);
+        let (incoming_tx, _outgoing_records, sync_service) =
+            new_sync_service(persister.clone(), signer.clone())?;
 
         for record in incoming_records {
             incoming_tx.send(record).await?;
         }
         sync_service.pull().await?;
 
-        if let Some(receive_swap) = persister.fetch_receive_swap_by_id(&sync_data[0].id())? {
+        if let Some(receive_swap) = persister.fetch_receive_swap_by_id(sync_data[0].id())? {
             assert!(receive_swap.description.is_none());
             assert!(receive_swap.payment_hash.is_none());
         } else {
             return Err(anyhow!("Receive swap not found"));
         }
-        if let Some(send_swap) = persister.fetch_send_swap_by_id(&sync_data[1].id())? {
+        if let Some(send_swap) = persister.fetch_send_swap_by_id(sync_data[1].id())? {
             assert!(send_swap.preimage.is_none());
             assert!(send_swap.description.is_none());
             assert!(send_swap.payment_hash.is_none());
         } else {
             return Err(anyhow!("Send swap not found"));
         }
-        if let Some(chain_swap) = persister.fetch_chain_swap_by_id(&sync_data[2].id())? {
+        if let Some(chain_swap) = persister.fetch_chain_swap_by_id(sync_data[2].id())? {
             assert!(chain_swap.claim_address.is_none());
             assert!(chain_swap.description.is_none());
             assert!(chain_swap.accept_zero_conf.eq(&true));
@@ -412,7 +420,6 @@ mod tests {
         let incoming_records = vec![
             Record::new(sync_data[0].clone(), 4, signer.clone())?,
             Record::new(sync_data[1].clone(), 5, signer.clone())?,
-            Record::new(sync_data[2].clone(), 6, signer.clone())?,
         ];
 
         for record in incoming_records {
@@ -420,12 +427,12 @@ mod tests {
         }
         sync_service.pull().await?;
 
-        if let Some(send_swap) = persister.fetch_send_swap_by_id(&sync_data[1].id())? {
+        if let Some(send_swap) = persister.fetch_send_swap_by_id(sync_data[0].id())? {
             assert_eq!(send_swap.preimage, new_preimage);
         } else {
             return Err(anyhow!("Send swap not found"));
         }
-        if let Some(chain_swap) = persister.fetch_chain_swap_by_id(&sync_data[2].id())? {
+        if let Some(chain_swap) = persister.fetch_chain_swap_by_id(sync_data[1].id())? {
             assert_eq!(chain_swap.accept_zero_conf, new_accept_zero_conf);
         } else {
             return Err(anyhow!("Chain swap not found"));
@@ -434,10 +441,10 @@ mod tests {
         Ok(())
     }
 
-    fn get_outgoing_record<'a, 'b>(
+    fn get_outgoing_record<'a>(
         persister: Arc<Persister>,
         outgoing: &'a HashMap<String, Record>,
-        data_id: &'b str,
+        data_id: &str,
         record_type: RecordType,
     ) -> Result<&'a Record> {
         let record_id = Record::get_id_from_record_type(record_type, data_id);
@@ -454,16 +461,11 @@ mod tests {
 
     #[tokio::test]
     async fn test_outgoing_sync() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
-
+        create_persister!(persister);
         let signer: Arc<Box<dyn Signer>> = Arc::new(Box::new(MockSigner::new()));
 
-        let (_incoming_tx, incoming_rx) = mpsc::channel::<Record>(10);
-        let outgoing_records = Arc::new(Mutex::new(HashMap::new()));
-        let client = Box::new(MockSyncerClient::new(incoming_rx, outgoing_records.clone()));
-        let sync_service =
-            SyncService::new("".to_string(), persister.clone(), signer.clone(), client);
+        let (_incoming_tx, outgoing_records, sync_service) =
+            new_sync_service(persister.clone(), signer.clone())?;
 
         // Test insert
         persister.insert_receive_swap(&new_receive_swap(None))?;
@@ -507,7 +509,7 @@ mod tests {
         persister.try_handle_send_swap_update(
             &swap.id,
             PaymentState::Pending,
-            new_preimage.clone(),
+            new_preimage,
             None,
             None,
         )?;
@@ -539,7 +541,7 @@ mod tests {
         persister.try_handle_send_swap_update(
             &swap.id,
             PaymentState::Pending,
-            new_preimage.clone(),
+            new_preimage,
             None,
             None,
         )?;
@@ -564,16 +566,11 @@ mod tests {
 
     #[tokio::test]
     async fn test_sync_clean() -> Result<()> {
-        let (_temp_dir, persister) = new_persister()?;
-        let persister = Arc::new(persister);
-
+        create_persister!(persister);
         let signer: Arc<Box<dyn Signer>> = Arc::new(Box::new(MockSigner::new()));
 
-        let (incoming_tx, incoming_rx) = mpsc::channel::<Record>(10);
-        let outgoing_records = Arc::new(Mutex::new(HashMap::new()));
-        let client = Box::new(MockSyncerClient::new(incoming_rx, outgoing_records.clone()));
-        let sync_service =
-            SyncService::new("".to_string(), persister.clone(), signer.clone(), client);
+        let (incoming_tx, _outgoing_records, sync_service) =
+            new_sync_service(persister.clone(), signer.clone())?;
 
         // Clean incoming
         let record = Record::new(
@@ -613,7 +610,7 @@ mod tests {
         persister.try_handle_send_swap_update(
             &swap.id,
             PaymentState::Pending,
-            new_preimage.clone(),
+            new_preimage,
             None,
             None,
         )?;
diff --git a/lib/core/src/sync/model/mod.rs b/lib/core/src/sync/model/mod.rs
index 98e460bce..6b63486ac 100644
--- a/lib/core/src/sync/model/mod.rs
+++ b/lib/core/src/sync/model/mod.rs
@@ -85,7 +85,7 @@ impl Record {
         let id = Self::get_id_from_sync_data(&data);
         let data = data.to_bytes()?;
         let data = signer
-            .ecies_encrypt(&data)
+            .ecies_encrypt(data)
             .map_err(|err| anyhow::anyhow!("Could not encrypt sync data: {err:?}"))?;
         let schema_version = CURRENT_SCHEMA_VERSION.to_string();
         Ok(Self {
@@ -126,7 +126,7 @@ impl Record {
     }
 
     pub(crate) fn decrypt(self, signer: Arc<Box<dyn Signer>>) -> Result<DecryptedRecord> {
-        let dec_data = signer.ecies_decrypt(self.data.as_slice())?;
+        let dec_data = signer.ecies_decrypt(self.data)?;
         let data = serde_json::from_slice(&dec_data)?;
         Ok(DecryptedRecord {
             id: self.id,
diff --git a/lib/core/src/wallet.rs b/lib/core/src/wallet.rs
index 1c91cfecb..e66c9ad31 100644
--- a/lib/core/src/wallet.rs
+++ b/lib/core/src/wallet.rs
@@ -377,12 +377,13 @@ mod tests {
     use super::*;
     use crate::model::Config;
     use crate::signer::SdkSigner;
-    use crate::test_utils::persist::new_persister;
+    use crate::test_utils::persist::create_persister;
     use crate::wallet::LiquidOnchainWallet;
-    use tempfile::TempDir;
+    use anyhow::Result;
+    use tempdir::TempDir;
 
     #[tokio::test]
-    async fn test_sign_and_check_message() {
+    async fn test_sign_and_check_message() -> Result<()> {
         let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
         let sdk_signer: Box<dyn Signer> = Box::new(SdkSigner::new(mnemonic, false).unwrap());
         let sdk_signer = Arc::new(sdk_signer);
@@ -390,11 +391,10 @@ mod tests {
         let config = Config::testnet(None);
 
         // Create a temporary directory for working_dir
-        let temp_dir = TempDir::new().unwrap();
+        let temp_dir = TempDir::new("").unwrap();
         let working_dir = temp_dir.path().to_str().unwrap().to_string();
 
-        let (_temp_dir, storage) = new_persister().unwrap();
-        let storage = Arc::new(storage);
+        create_persister!(storage);
 
         let wallet: Arc<dyn OnchainWallet> = Arc::new(
             LiquidOnchainWallet::new(config, &working_dir, storage, sdk_signer.clone()).unwrap(),
@@ -444,5 +444,6 @@ mod tests {
         );
 
         // The temporary directory will be automatically deleted when temp_dir goes out of scope
+        Ok(())
     }
 }
diff --git a/packages/dart/lib/src/frb_generated.dart b/packages/dart/lib/src/frb_generated.dart
index d7fd63a98..65cb1a8b0 100644
--- a/packages/dart/lib/src/frb_generated.dart
+++ b/packages/dart/lib/src/frb_generated.dart
@@ -1682,7 +1682,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
   Config dco_decode_config(dynamic raw) {
     // Codec=Dco (DartCObject based), see doc to use other codecs
     final arr = raw as List<dynamic>;
-    if (arr.length != 10) throw Exception('unexpected arr length: expect 10 but see ${arr.length}');
+    if (arr.length != 11) throw Exception('unexpected arr length: expect 11 but see ${arr.length}');
     return Config(
       liquidElectrumUrl: dco_decode_String(arr[0]),
       bitcoinElectrumUrl: dco_decode_String(arr[1]),
@@ -1692,8 +1692,9 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
       network: dco_decode_liquid_network(arr[5]),
       paymentTimeoutSec: dco_decode_u_64(arr[6]),
       zeroConfMinFeeRateMsat: dco_decode_u_32(arr[7]),
-      zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[8]),
-      breezApiKey: dco_decode_opt_String(arr[9]),
+      syncServiceUrl: dco_decode_String(arr[8]),
+      zeroConfMaxAmountSat: dco_decode_opt_box_autoadd_u_64(arr[9]),
+      breezApiKey: dco_decode_opt_String(arr[10]),
     );
   }
 
@@ -3560,6 +3561,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
     var var_network = sse_decode_liquid_network(deserializer);
     var var_paymentTimeoutSec = sse_decode_u_64(deserializer);
     var var_zeroConfMinFeeRateMsat = sse_decode_u_32(deserializer);
+    var var_syncServiceUrl = sse_decode_String(deserializer);
     var var_zeroConfMaxAmountSat = sse_decode_opt_box_autoadd_u_64(deserializer);
     var var_breezApiKey = sse_decode_opt_String(deserializer);
     return Config(
@@ -3571,6 +3573,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
         network: var_network,
         paymentTimeoutSec: var_paymentTimeoutSec,
         zeroConfMinFeeRateMsat: var_zeroConfMinFeeRateMsat,
+        syncServiceUrl: var_syncServiceUrl,
         zeroConfMaxAmountSat: var_zeroConfMaxAmountSat,
         breezApiKey: var_breezApiKey);
   }
@@ -5578,6 +5581,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
     sse_encode_liquid_network(self.network, serializer);
     sse_encode_u_64(self.paymentTimeoutSec, serializer);
     sse_encode_u_32(self.zeroConfMinFeeRateMsat, serializer);
+    sse_encode_String(self.syncServiceUrl, serializer);
     sse_encode_opt_box_autoadd_u_64(self.zeroConfMaxAmountSat, serializer);
     sse_encode_opt_String(self.breezApiKey, serializer);
   }
diff --git a/packages/dart/lib/src/frb_generated.io.dart b/packages/dart/lib/src/frb_generated.io.dart
index 85e594835..8ebf6b025 100644
--- a/packages/dart/lib/src/frb_generated.io.dart
+++ b/packages/dart/lib/src/frb_generated.io.dart
@@ -2149,6 +2149,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
     wireObj.network = cst_encode_liquid_network(apiObj.network);
     wireObj.payment_timeout_sec = cst_encode_u_64(apiObj.paymentTimeoutSec);
     wireObj.zero_conf_min_fee_rate_msat = cst_encode_u_32(apiObj.zeroConfMinFeeRateMsat);
+    wireObj.sync_service_url = cst_encode_String(apiObj.syncServiceUrl);
     wireObj.zero_conf_max_amount_sat = cst_encode_opt_box_autoadd_u_64(apiObj.zeroConfMaxAmountSat);
     wireObj.breez_api_key = cst_encode_opt_String(apiObj.breezApiKey);
   }
@@ -5922,6 +5923,8 @@ final class wire_cst_config extends ffi.Struct {
   @ffi.Uint32()
   external int zero_conf_min_fee_rate_msat;
 
+  external ffi.Pointer<wire_cst_list_prim_u_8_strict> sync_service_url;
+
   external ffi.Pointer<ffi.Uint64> zero_conf_max_amount_sat;
 
   external ffi.Pointer<wire_cst_list_prim_u_8_strict> breez_api_key;
diff --git a/packages/dart/lib/src/model.dart b/packages/dart/lib/src/model.dart
index 87063eed6..16c963862 100644
--- a/packages/dart/lib/src/model.dart
+++ b/packages/dart/lib/src/model.dart
@@ -134,6 +134,9 @@ class Config {
   /// Zero-conf minimum accepted fee-rate in millisatoshis per vbyte
   final int zeroConfMinFeeRateMsat;
 
+  /// The url of the real-time sync service
+  final String syncServiceUrl;
+
   /// Maximum amount in satoshi to accept zero-conf payments with
   /// Defaults to [crate::receive_swap::DEFAULT_ZERO_CONF_MAX_SAT]
   final BigInt? zeroConfMaxAmountSat;
@@ -150,6 +153,7 @@ class Config {
     required this.network,
     required this.paymentTimeoutSec,
     required this.zeroConfMinFeeRateMsat,
+    required this.syncServiceUrl,
     this.zeroConfMaxAmountSat,
     this.breezApiKey,
   });
@@ -164,6 +168,7 @@ class Config {
       network.hashCode ^
       paymentTimeoutSec.hashCode ^
       zeroConfMinFeeRateMsat.hashCode ^
+      syncServiceUrl.hashCode ^
       zeroConfMaxAmountSat.hashCode ^
       breezApiKey.hashCode;
 
@@ -180,6 +185,7 @@ class Config {
           network == other.network &&
           paymentTimeoutSec == other.paymentTimeoutSec &&
           zeroConfMinFeeRateMsat == other.zeroConfMinFeeRateMsat &&
+          syncServiceUrl == other.syncServiceUrl &&
           zeroConfMaxAmountSat == other.zeroConfMaxAmountSat &&
           breezApiKey == other.breezApiKey;
 }
@@ -730,6 +736,12 @@ enum PaymentState {
   ///
   /// When the refund tx is broadcast, `refund_tx_id` is set in the swap.
   refundPending,
+
+  /// ## Recoverable Swaps
+  ///
+  /// The status for swaps that have been synced in, and whose information is recoverable from
+  /// chain
+  recoverable,
   ;
 }
 
diff --git a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart
index 3ec45f173..34e339463 100644
--- a/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart
+++ b/packages/flutter/lib/flutter_breez_liquid_bindings_generated.dart
@@ -4506,6 +4506,8 @@ final class wire_cst_config extends ffi.Struct {
   @ffi.Uint32()
   external int zero_conf_min_fee_rate_msat;
 
+  external ffi.Pointer<wire_cst_list_prim_u_8_strict> sync_service_url;
+
   external ffi.Pointer<ffi.Uint64> zero_conf_max_amount_sat;
 
   external ffi.Pointer<wire_cst_list_prim_u_8_strict> breez_api_key;
diff --git a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt
index d4ce62613..a10c7568b 100644
--- a/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt
+++ b/packages/react-native/android/src/main/java/com/breezsdkliquid/BreezSDKLiquidMapper.kt
@@ -248,6 +248,7 @@ fun asConfig(config: ReadableMap): Config? {
                 "network",
                 "paymentTimeoutSec",
                 "zeroConfMinFeeRateMsat",
+                "syncServiceUrl",
             ),
         )
     ) {
@@ -260,6 +261,7 @@ fun asConfig(config: ReadableMap): Config? {
     val network = config.getString("network")?.let { asLiquidNetwork(it) }!!
     val paymentTimeoutSec = config.getDouble("paymentTimeoutSec").toULong()
     val zeroConfMinFeeRateMsat = config.getInt("zeroConfMinFeeRateMsat").toUInt()
+    val syncServiceUrl = config.getString("syncServiceUrl")!!
     val breezApiKey = if (hasNonNullKey(config, "breezApiKey")) config.getString("breezApiKey") else null
     val cacheDir = if (hasNonNullKey(config, "cacheDir")) config.getString("cacheDir") else null
     val zeroConfMaxAmountSat =
@@ -280,6 +282,7 @@ fun asConfig(config: ReadableMap): Config? {
         network,
         paymentTimeoutSec,
         zeroConfMinFeeRateMsat,
+        syncServiceUrl,
         breezApiKey,
         cacheDir,
         zeroConfMaxAmountSat,
@@ -295,6 +298,7 @@ fun readableMapOf(config: Config): ReadableMap =
         "network" to config.network.name.lowercase(),
         "paymentTimeoutSec" to config.paymentTimeoutSec,
         "zeroConfMinFeeRateMsat" to config.zeroConfMinFeeRateMsat,
+        "syncServiceUrl" to config.syncServiceUrl,
         "breezApiKey" to config.breezApiKey,
         "cacheDir" to config.cacheDir,
         "zeroConfMaxAmountSat" to config.zeroConfMaxAmountSat,
diff --git a/packages/react-native/ios/BreezSDKLiquidMapper.swift b/packages/react-native/ios/BreezSDKLiquidMapper.swift
index 2a647dc68..1803382bf 100644
--- a/packages/react-native/ios/BreezSDKLiquidMapper.swift
+++ b/packages/react-native/ios/BreezSDKLiquidMapper.swift
@@ -307,6 +307,9 @@ enum BreezSDKLiquidMapper {
         guard let zeroConfMinFeeRateMsat = config["zeroConfMinFeeRateMsat"] as? UInt32 else {
             throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "zeroConfMinFeeRateMsat", typeName: "Config"))
         }
+        guard let syncServiceUrl = config["syncServiceUrl"] as? String else {
+            throw SdkError.Generic(message: errMissingMandatoryField(fieldName: "syncServiceUrl", typeName: "Config"))
+        }
         var breezApiKey: String?
         if hasNonNilKey(data: config, key: "breezApiKey") {
             guard let breezApiKeyTmp = config["breezApiKey"] as? String else {
@@ -329,7 +332,7 @@ enum BreezSDKLiquidMapper {
             zeroConfMaxAmountSat = zeroConfMaxAmountSatTmp
         }
 
-        return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, breezApiKey: breezApiKey, cacheDir: cacheDir, zeroConfMaxAmountSat: zeroConfMaxAmountSat)
+        return Config(liquidElectrumUrl: liquidElectrumUrl, bitcoinElectrumUrl: bitcoinElectrumUrl, mempoolspaceUrl: mempoolspaceUrl, workingDir: workingDir, network: network, paymentTimeoutSec: paymentTimeoutSec, zeroConfMinFeeRateMsat: zeroConfMinFeeRateMsat, syncServiceUrl: syncServiceUrl, breezApiKey: breezApiKey, cacheDir: cacheDir, zeroConfMaxAmountSat: zeroConfMaxAmountSat)
     }
 
     static func dictionaryOf(config: Config) -> [String: Any?] {
@@ -341,6 +344,7 @@ enum BreezSDKLiquidMapper {
             "network": valueOf(liquidNetwork: config.network),
             "paymentTimeoutSec": config.paymentTimeoutSec,
             "zeroConfMinFeeRateMsat": config.zeroConfMinFeeRateMsat,
+            "syncServiceUrl": config.syncServiceUrl,
             "breezApiKey": config.breezApiKey == nil ? nil : config.breezApiKey,
             "cacheDir": config.cacheDir == nil ? nil : config.cacheDir,
             "zeroConfMaxAmountSat": config.zeroConfMaxAmountSat == nil ? nil : config.zeroConfMaxAmountSat,
@@ -3729,6 +3733,9 @@ enum BreezSDKLiquidMapper {
         case "refundPending":
             return PaymentState.refundPending
 
+        case "recoverable":
+            return PaymentState.recoverable
+
         default: throw SdkError.Generic(message: "Invalid variant \(paymentState) for enum PaymentState")
         }
     }
@@ -3755,6 +3762,9 @@ enum BreezSDKLiquidMapper {
 
         case .refundPending:
             return "refundPending"
+
+        case .recoverable:
+            return "recoverable"
         }
     }
 
diff --git a/packages/react-native/src/index.ts b/packages/react-native/src/index.ts
index fe71196f5..431289ea9 100644
--- a/packages/react-native/src/index.ts
+++ b/packages/react-native/src/index.ts
@@ -65,6 +65,7 @@ export interface Config {
     network: LiquidNetwork
     paymentTimeoutSec: number
     zeroConfMinFeeRateMsat: number
+    syncServiceUrl: string
     breezApiKey?: string
     cacheDir?: string
     zeroConfMaxAmountSat?: number
@@ -620,7 +621,8 @@ export enum PaymentState {
     FAILED = "failed",
     TIMED_OUT = "timedOut",
     REFUNDABLE = "refundable",
-    REFUND_PENDING = "refundPending"
+    REFUND_PENDING = "refundPending",
+    RECOVERABLE = "recoverable"
 }
 
 export enum PaymentType {


Test patch:
diff --git a/lib/core/src/test_utils/persist.rs b/lib/core/src/test_utils/persist.rs
index ce024bf00..fcad33ef8 100644
--- a/lib/core/src/test_utils/persist.rs
+++ b/lib/core/src/test_utils/persist.rs
@@ -1,6 +1,5 @@
 #![cfg(test)]
 
-use anyhow::{anyhow, Result};
 use bip39::rand::{self, RngCore};
 use sdk_common::{
     bitcoin::{
@@ -10,11 +9,9 @@ use sdk_common::{
     lightning::ln::PaymentSecret,
     lightning_invoice::{Currency, InvoiceBuilder},
 };
-use tempdir::TempDir;
 
 use crate::{
-    model::{LiquidNetwork, PaymentState, PaymentTxData, PaymentType, ReceiveSwap, SendSwap},
-    persist::Persister,
+    model::{PaymentState, PaymentTxData, PaymentType, ReceiveSwap, SendSwap},
     test_utils::generate_random_string,
     utils,
 };
@@ -113,18 +110,22 @@ pub(crate) fn new_receive_swap(payment_state: Option<PaymentState>) -> ReceiveSw
     }
 }
 
-pub(crate) fn new_persister() -> Result<(TempDir, Persister)> {
-    let temp_dir = TempDir::new("liquid-sdk")?;
-    let persister = Persister::new(
-        temp_dir
-            .path()
-            .to_str()
-            .ok_or(anyhow!("Could not create temporary directory"))?,
-        LiquidNetwork::Testnet,
-    )?;
-    persister.init()?;
-    Ok((temp_dir, persister))
+macro_rules! create_persister {
+    ($name:ident) => {
+        let (sync_trigger_tx, _sync_trigger_rx) = tokio::sync::mpsc::channel::<()>(100);
+        let temp_dir = tempdir::TempDir::new("liquid-sdk")?;
+        let $name = std::sync::Arc::new(crate::persist::Persister::new(
+            temp_dir
+                .path()
+                .to_str()
+                .ok_or(anyhow::anyhow!("Could not create temporary directory"))?,
+            crate::model::LiquidNetwork::Testnet,
+            sync_trigger_tx,
+        )?);
+        $name.init()?;
+    };
 }
+pub(crate) use create_persister;
 
 pub(crate) fn new_payment_tx_data(payment_type: PaymentType) -> PaymentTxData {
     PaymentTxData {
diff --git a/lib/core/src/test_utils/sdk.rs b/lib/core/src/test_utils/sdk.rs
index ae34026bb..52326f7d7 100644
--- a/lib/core/src/test_utils/sdk.rs
+++ b/lib/core/src/test_utils/sdk.rs
@@ -21,6 +21,7 @@ use super::{
     chain::{MockBitcoinChainService, MockLiquidChainService},
     status_stream::MockStatusStream,
     swapper::MockSwapper,
+    sync::new_sync_service,
     wallet::{MockSigner, MockWallet},
 };
 
@@ -91,6 +92,10 @@ pub(crate) fn new_liquid_sdk_with_chain_services(
     let buy_bitcoin_service =
         Arc::new(BuyBitcoinService::new(config.clone(), breez_server.clone()));
 
+    let (_incoming_tx, _outgoing_records, sync_service) =
+        new_sync_service(persister.clone(), signer.clone())?;
+    let sync_service = Arc::new(sync_service);
+
     Ok(LiquidSdk {
         config,
         onchain_wallet,
@@ -107,6 +112,7 @@ pub(crate) fn new_liquid_sdk_with_chain_services(
         shutdown_receiver,
         send_swap_handler,
         receive_swap_handler,
+        sync_service,
         chain_swap_handler,
         buy_bitcoin_service,
     })
diff --git a/lib/core/src/test_utils/sync.rs b/lib/core/src/test_utils/sync.rs
index a451ced46..06b979a36 100644
--- a/lib/core/src/test_utils/sync.rs
+++ b/lib/core/src/test_utils/sync.rs
@@ -3,7 +3,8 @@
 use std::{collections::HashMap, sync::Arc};
 
 use crate::{
-    prelude::Direction,
+    persist::Persister,
+    prelude::{Direction, Signer},
     sync::{
         client::SyncerClient,
         model::{
@@ -13,11 +14,15 @@ use crate::{
                 SetRecordStatus,
             },
         },
+        SyncService,
     },
 };
 use anyhow::Result;
 use async_trait::async_trait;
-use tokio::sync::{mpsc::Receiver, Mutex};
+use tokio::sync::{
+    mpsc::{self, Receiver, Sender},
+    Mutex,
+};
 
 pub(crate) struct MockSyncerClient {
     pub(crate) incoming_rx: Mutex<Receiver<Record>>,
@@ -80,6 +85,30 @@ impl SyncerClient for MockSyncerClient {
     }
 }
 
+#[allow(clippy::type_complexity)]
+pub(crate) fn new_sync_service(
+    persister: Arc<Persister>,
+    signer: Arc<Box<dyn Signer>>,
+) -> Result<(
+    Sender<Record>,
+    Arc<Mutex<HashMap<String, Record>>>,
+    SyncService,
+)> {
+    let (_, sync_trigger_rx) = mpsc::channel::<()>(30);
+    let (incoming_tx, incoming_rx) = mpsc::channel::<Record>(10);
+    let outgoing_records = Arc::new(Mutex::new(HashMap::new()));
+    let client = Box::new(MockSyncerClient::new(incoming_rx, outgoing_records.clone()));
+    let sync_service = SyncService::new(
+        "".to_string(),
+        persister.clone(),
+        signer.clone(),
+        client,
+        sync_trigger_rx,
+    );
+
+    Ok((incoming_tx, outgoing_records, sync_service))
+}
+
 pub(crate) fn new_receive_sync_data() -> ReceiveSyncData {
     ReceiveSyncData {
         swap_id: "receive-swap".to_string(),
diff --git a/lib/core/src/test_utils/wallet.rs b/lib/core/src/test_utils/wallet.rs
index db32c6060..3f1d32919 100644
--- a/lib/core/src/test_utils/wallet.rs
+++ b/lib/core/src/test_utils/wallet.rs
@@ -139,21 +139,17 @@ impl Signer for MockSigner {
         todo!()
     }
 
-    fn ecies_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
+    fn ecies_encrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
         let rc_pub = self.keypair.public_key().to_public_key().to_bytes();
-        Ok(
-            ecies::encrypt(&rc_pub, msg).map_err(|err| SignerError::Generic {
-                err: format!("Could not encrypt data: {err}"),
-            })?,
-        )
+        ecies::encrypt(&rc_pub, &msg).map_err(|err| SignerError::Generic {
+            err: format!("Could not encrypt data: {err}"),
+        })
     }
 
-    fn ecies_decrypt(&self, msg: &[u8]) -> Result<Vec<u8>, SignerError> {
+    fn ecies_decrypt(&self, msg: Vec<u8>) -> Result<Vec<u8>, SignerError> {
         let rc_prv = self.keypair.secret_bytes();
-        Ok(
-            ecies::decrypt(&rc_prv, msg).map_err(|err| SignerError::Generic {
-                err: format!("Could not decrypt data: {err}"),
-            })?,
-        )
+        ecies::decrypt(&rc_prv, &msg).map_err(|err| SignerError::Generic {
+            err: format!("Could not decrypt data: {err}"),
+        })
     }
 }