From b40063857b1bcf120d7d36ff2a61c391e494643b Mon Sep 17 00:00:00 2001 From: arkanoider Date: Sat, 28 Dec 2024 12:58:24 +0100 Subject: [PATCH 1/3] first commit --- Cargo.lock | 1052 ++-- Cargo.toml | 26 +- mostro-cli/.env-sample | 7 + mostro-cli/.github/workflows/rust.yml | 22 + mostro-cli/Cargo.lock | 3727 ++++++++++++++ mostro-cli/Cargo.toml | 41 + mostro-cli/LICENSE | 21 + mostro-cli/README.md | 102 + archs => mostro-cli/archs | 0 mostro-cli/cross-compile.sh | 28 + .../rust-toolchain.toml | 0 mostro-cli/src/cli.rs | 437 ++ mostro-cli/src/cli/add_invoice.rs | 81 + mostro-cli/src/cli/conversation_key.rs | 17 + mostro-cli/src/cli/get_dm.rs | 72 + mostro-cli/src/cli/list_disputes.rs | 19 + mostro-cli/src/cli/list_orders.rs | 63 + mostro-cli/src/cli/new_order.rs | 188 + mostro-cli/src/cli/rate_user.rs | 65 + mostro-cli/src/cli/send_dm.rs | 39 + mostro-cli/src/cli/send_msg.rs | 76 + mostro-cli/src/cli/take_buy.rs | 100 + mostro-cli/src/cli/take_dispute.rs | 41 + mostro-cli/src/cli/take_sell.rs | 123 + mostro-cli/src/db.rs | 433 ++ mostro-cli/src/error.rs | 42 + mostro-cli/src/fiat.rs | 1468 ++++++ mostro-cli/src/lib.rs | 7 + mostro-cli/src/lightning/mod.rs | 13 + mostro-cli/src/main.rs | 16 + mostro-cli/src/nip33.rs | 89 + mostro-cli/src/pretty_table.rs | 250 + mostro-cli/src/util.rs | 406 ++ {static => mostro-cli/static}/logo.png | Bin mostro-core/.github/workflows/rust.yml | 22 + mostro-core/Cargo.lock | 2539 ++++++++++ mostro-core/Cargo.toml | 29 + mostro-core/LICENSE | 21 + mostro-core/README.md | 1 + mostro-core/rust-toolchain.toml | 5 + mostro-core/src/dispute.rs | 82 + mostro-core/src/lib.rs | 183 + mostro-core/src/message.rs | 425 ++ mostro-core/src/order.rs | 274 ++ mostro-core/src/rating.rs | 108 + mostro-core/src/user.rs | 50 + .../.github}/workflows/rust.yml | 0 CONTRIBUTING.md => mostro/CONTRIBUTING.md | 0 mostro/Cargo.lock | 4303 +++++++++++++++++ mostro/Cargo.toml | 37 + Cross.toml => mostro/Cross.toml | 0 INSTALL.md => mostro/INSTALL.md | 0 LICENSE => mostro/LICENSE | 0 Makefile => mostro/Makefile | 0 README.md => mostro/README.md | 0 mostro/archs | 7 + build.rs => mostro/build.rs | 0 cross-compile.sh => mostro/cross-compile.sh | 0 {docker => mostro/docker}/.env.example | 0 {docker => mostro/docker}/Dockerfile | 0 {docker => mostro/docker}/README.md | 0 {docker => mostro/docker}/compose.yml | 0 {docker => mostro/docker}/empty.mostro.db | Bin {docker => mostro/docker}/relay_config.toml | 0 .../docker}/settings.docker.toml | 0 {docker => mostro/docker}/start.sh | 0 init_db.sh => mostro/init_db.sh | 0 {keys => mostro/keys}/negrunch.asc | 0 .../migrations}/20221222153301_orders.sql | 0 .../migrations}/20230928145530_disputes.sql | 0 .../migrations}/20231005195154_users.sql | 0 mostro/rust-toolchain.toml | 5 + settings.tpl.toml => mostro/settings.tpl.toml | 0 sqlx-data.json => mostro/sqlx-data.json | 0 {src => mostro/src}/app.rs | 0 {src => mostro/src}/app/add_invoice.rs | 0 {src => mostro/src}/app/admin_add_solver.rs | 0 {src => mostro/src}/app/admin_cancel.rs | 0 {src => mostro/src}/app/admin_settle.rs | 0 {src => mostro/src}/app/admin_take_dispute.rs | 0 {src => mostro/src}/app/cancel.rs | 0 {src => mostro/src}/app/dispute.rs | 0 {src => mostro/src}/app/fiat_sent.rs | 0 {src => mostro/src}/app/order.rs | 0 {src => mostro/src}/app/rate_user.rs | 0 {src => mostro/src}/app/release.rs | 0 {src => mostro/src}/app/take_buy.rs | 0 {src => mostro/src}/app/take_sell.rs | 0 {src => mostro/src}/bitcoin_price.rs | 0 {src => mostro/src}/cli.rs | 0 {src => mostro/src}/cli/settings.rs | 0 {src => mostro/src}/db.rs | 0 {src => mostro/src}/error.rs | 0 {src => mostro/src}/flow.rs | 0 {src => mostro/src}/lightning/invoice.rs | 0 {src => mostro/src}/lightning/mod.rs | 0 {src => mostro/src}/lnurl.rs | 0 {src => mostro/src}/main.rs | 0 {src => mostro/src}/messages.rs | 0 {src => mostro/src}/models.rs | 0 {src => mostro/src}/nip33.rs | 0 {src => mostro/src}/nip59.rs | 0 {src => mostro/src}/scheduler.rs | 0 {src => mostro/src}/util.rs | 0 mostro/static/logo.png | Bin 0 -> 84471 bytes 105 files changed, 16860 insertions(+), 302 deletions(-) create mode 100644 mostro-cli/.env-sample create mode 100644 mostro-cli/.github/workflows/rust.yml create mode 100644 mostro-cli/Cargo.lock create mode 100644 mostro-cli/Cargo.toml create mode 100644 mostro-cli/LICENSE create mode 100644 mostro-cli/README.md rename archs => mostro-cli/archs (100%) create mode 100755 mostro-cli/cross-compile.sh rename rust-toolchain.toml => mostro-cli/rust-toolchain.toml (100%) create mode 100644 mostro-cli/src/cli.rs create mode 100644 mostro-cli/src/cli/add_invoice.rs create mode 100644 mostro-cli/src/cli/conversation_key.rs create mode 100644 mostro-cli/src/cli/get_dm.rs create mode 100644 mostro-cli/src/cli/list_disputes.rs create mode 100644 mostro-cli/src/cli/list_orders.rs create mode 100644 mostro-cli/src/cli/new_order.rs create mode 100644 mostro-cli/src/cli/rate_user.rs create mode 100644 mostro-cli/src/cli/send_dm.rs create mode 100644 mostro-cli/src/cli/send_msg.rs create mode 100644 mostro-cli/src/cli/take_buy.rs create mode 100644 mostro-cli/src/cli/take_dispute.rs create mode 100644 mostro-cli/src/cli/take_sell.rs create mode 100644 mostro-cli/src/db.rs create mode 100644 mostro-cli/src/error.rs create mode 100644 mostro-cli/src/fiat.rs create mode 100644 mostro-cli/src/lib.rs create mode 100644 mostro-cli/src/lightning/mod.rs create mode 100644 mostro-cli/src/main.rs create mode 100644 mostro-cli/src/nip33.rs create mode 100644 mostro-cli/src/pretty_table.rs create mode 100644 mostro-cli/src/util.rs rename {static => mostro-cli/static}/logo.png (100%) create mode 100644 mostro-core/.github/workflows/rust.yml create mode 100644 mostro-core/Cargo.lock create mode 100644 mostro-core/Cargo.toml create mode 100644 mostro-core/LICENSE create mode 100644 mostro-core/README.md create mode 100644 mostro-core/rust-toolchain.toml create mode 100644 mostro-core/src/dispute.rs create mode 100644 mostro-core/src/lib.rs create mode 100644 mostro-core/src/message.rs create mode 100644 mostro-core/src/order.rs create mode 100644 mostro-core/src/rating.rs create mode 100644 mostro-core/src/user.rs rename {.github => mostro/.github}/workflows/rust.yml (100%) rename CONTRIBUTING.md => mostro/CONTRIBUTING.md (100%) create mode 100644 mostro/Cargo.lock create mode 100644 mostro/Cargo.toml rename Cross.toml => mostro/Cross.toml (100%) rename INSTALL.md => mostro/INSTALL.md (100%) rename LICENSE => mostro/LICENSE (100%) rename Makefile => mostro/Makefile (100%) rename README.md => mostro/README.md (100%) create mode 100644 mostro/archs rename build.rs => mostro/build.rs (100%) rename cross-compile.sh => mostro/cross-compile.sh (100%) rename {docker => mostro/docker}/.env.example (100%) rename {docker => mostro/docker}/Dockerfile (100%) rename {docker => mostro/docker}/README.md (100%) rename {docker => mostro/docker}/compose.yml (100%) rename {docker => mostro/docker}/empty.mostro.db (100%) rename {docker => mostro/docker}/relay_config.toml (100%) rename {docker => mostro/docker}/settings.docker.toml (100%) rename {docker => mostro/docker}/start.sh (100%) rename init_db.sh => mostro/init_db.sh (100%) rename {keys => mostro/keys}/negrunch.asc (100%) rename {migrations => mostro/migrations}/20221222153301_orders.sql (100%) rename {migrations => mostro/migrations}/20230928145530_disputes.sql (100%) rename {migrations => mostro/migrations}/20231005195154_users.sql (100%) create mode 100644 mostro/rust-toolchain.toml rename settings.tpl.toml => mostro/settings.tpl.toml (100%) rename sqlx-data.json => mostro/sqlx-data.json (100%) rename {src => mostro/src}/app.rs (100%) rename {src => mostro/src}/app/add_invoice.rs (100%) rename {src => mostro/src}/app/admin_add_solver.rs (100%) rename {src => mostro/src}/app/admin_cancel.rs (100%) rename {src => mostro/src}/app/admin_settle.rs (100%) rename {src => mostro/src}/app/admin_take_dispute.rs (100%) rename {src => mostro/src}/app/cancel.rs (100%) rename {src => mostro/src}/app/dispute.rs (100%) rename {src => mostro/src}/app/fiat_sent.rs (100%) rename {src => mostro/src}/app/order.rs (100%) rename {src => mostro/src}/app/rate_user.rs (100%) rename {src => mostro/src}/app/release.rs (100%) rename {src => mostro/src}/app/take_buy.rs (100%) rename {src => mostro/src}/app/take_sell.rs (100%) rename {src => mostro/src}/bitcoin_price.rs (100%) rename {src => mostro/src}/cli.rs (100%) rename {src => mostro/src}/cli/settings.rs (100%) rename {src => mostro/src}/db.rs (100%) rename {src => mostro/src}/error.rs (100%) rename {src => mostro/src}/flow.rs (100%) rename {src => mostro/src}/lightning/invoice.rs (100%) rename {src => mostro/src}/lightning/mod.rs (100%) rename {src => mostro/src}/lnurl.rs (100%) rename {src => mostro/src}/main.rs (100%) rename {src => mostro/src}/messages.rs (100%) rename {src => mostro/src}/models.rs (100%) rename {src => mostro/src}/nip33.rs (100%) rename {src => mostro/src}/nip59.rs (100%) rename {src => mostro/src}/scheduler.rs (100%) rename {src => mostro/src}/util.rs (100%) create mode 100644 mostro/static/logo.png diff --git a/Cargo.lock b/Cargo.lock index d44978d2..36ac7bdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arraydeque" @@ -187,7 +187,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -198,7 +198,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -208,24 +208,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a349201d80b4aa18d17a34a182bdd7f8ddf845e9e57d2ea130a12e10ef1e3a47" dependencies = [ "futures-util", - "gloo-timers", + "gloo-timers 0.2.6", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-utility" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" +dependencies = [ + "futures-util", + "gloo-timers 0.3.0", "tokio", "wasm-bindgen-futures", ] [[package]] name = "async-wsocket" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a107e3bdbe61e8e1e1341c57241b4b2d50501127b44bd2eff13b4635ab42d35a" +checksum = "8d50cb541e6d09e119e717c64c46ed33f49be7fa592fa805d56c11d6a7ff093c" dependencies = [ - "async-utility", + "async-utility 0.2.0", "futures", "futures-util", "js-sys", - "thiserror", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", + "tokio-socks", + "tokio-tungstenite", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "async-wsocket" +version = "0.11.0" +source = "git+https://github.com/yukibtc/async-wsocket?rev=259c0bc372e7d60d94827b484178bf995afdcbe6#259c0bc372e7d60d94827b484178bf995afdcbe6" +dependencies = [ + "async-utility 0.3.1", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls 0.26.1", "tokio-socks", "tokio-tungstenite", "url", @@ -251,6 +280,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "atomic-destructor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -276,7 +311,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "itoa", "matchit", "memchr", @@ -286,7 +321,7 @@ dependencies = [ "rustversion", "serde", "sync_wrapper 0.1.2", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", ] @@ -320,7 +355,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -370,10 +405,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" dependencies = [ "bitcoin_hashes 0.13.0", + "rand", + "rand_core", "serde", "unicode-normalization", ] +[[package]] +name = "bitcoin" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +dependencies = [ + "bech32 0.9.1", + "bitcoin_hashes 0.11.0", + "secp256k1 0.24.3", +] + [[package]] name = "bitcoin" version = "0.32.5" @@ -388,7 +436,7 @@ dependencies = [ "bitcoin_hashes 0.14.0", "hex-conservative 0.2.1", "hex_lit", - "secp256k1", + "secp256k1 0.29.1", "serde", ] @@ -438,6 +486,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + [[package]] name = "bitcoin_hashes" version = "0.13.0" @@ -549,9 +603,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cbc" @@ -564,9 +618,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.36" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "shlex", ] @@ -603,16 +657,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -628,9 +682,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -638,9 +692,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -657,14 +711,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -672,6 +726,18 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "comfy-table" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width", +] + [[package]] name = "config" version = "0.14.1" @@ -738,9 +804,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -792,18 +858,40 @@ checksum = "b31d2174830f395fd7e413c2f8a119252de36356982f805f495269331e97559e" [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "parking_lot 0.12.3", + "rustix", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] [[package]] name = "crunchy" @@ -848,6 +936,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -856,7 +965,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -918,6 +1027,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -926,12 +1048,12 @@ 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]] @@ -948,9 +1070,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fedimint-tonic-lnd" @@ -960,7 +1082,7 @@ checksum = "df03ca33b5116de3051c1e233fe341e23b04c4913c7b16042497924559bc2a2e" dependencies = [ "hex", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-rustls 0.24.2", "prost", "rustls 0.21.12", @@ -969,7 +1091,7 @@ dependencies = [ "tokio-stream", "tonic", "tonic-build", - "tower", + "tower 0.4.13", ] [[package]] @@ -980,9 +1102,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1008,9 +1130,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "foreign-types" @@ -1103,7 +1225,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -1186,6 +1308,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.3.26" @@ -1198,7 +1332,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -1207,17 +1341,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.6.0", + "http 1.2.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -1242,9 +1376,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -1277,9 +1411,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -1339,9 +1473,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", @@ -1366,7 +1500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1377,7 +1511,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1394,11 +1528,17 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -1420,15 +1560,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" 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", "itoa", @@ -1446,7 +1586,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -1454,18 +1594,18 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.5.0", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", - "rustls 0.23.16", + "rustls 0.23.20", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", ] @@ -1475,7 +1615,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.31", + "hyper 0.14.32", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -1489,7 +1629,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.2", "hyper-util", "native-tls", "tokio", @@ -1506,9 +1646,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.0", + "hyper 1.5.2", "pin-project-lite", "socket2", "tokio", @@ -1654,7 +1794,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -1690,12 +1830,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -1726,6 +1866,17 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -1743,16 +1894,17 @@ dependencies = [ [[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.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1784,9 +1936,19 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] [[package]] name = "libsqlite3-sys" @@ -1799,6 +1961,29 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "lightning" +version = "0.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e009e1c0c21f66378b491bb40f548682138c63e09db6f3a05af59f8804bb9f4a" +dependencies = [ + "bitcoin 0.29.2", +] + +[[package]] +name = "lightning-invoice" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e44b0e2822c8811470137d2339fdfe67a699b3248bb1606d1d02eb6a1e9f0a" +dependencies = [ + "bech32 0.9.1", + "bitcoin 0.29.2", + "bitcoin_hashes 0.11.0", + "lightning", + "num-traits", + "secp256k1 0.24.3", +] + [[package]] name = "lightning-invoice" version = "0.32.0" @@ -1806,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ab9f6ea77e20e3129235e62a2e6bd64ed932363df104e864ee65ccffb54a8f" dependencies = [ "bech32 0.9.1", - "bitcoin", + "bitcoin 0.32.5", "lightning-types", ] @@ -1817,7 +2002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1083b8d9137000edf3bfcb1ff011c0d25e0cdd2feb98cc21d6765e64a494148f" dependencies = [ "bech32 0.9.1", - "bitcoin", + "bitcoin 0.32.5", "hex-conservative 0.2.1", ] @@ -1829,9 +2014,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lnurl-rs" @@ -1843,7 +2028,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bech32 0.11.0", - "bitcoin", + "bitcoin 0.32.5", "cbc", "email_address", "reqwest", @@ -1875,7 +2060,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -1942,20 +2127,19 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] [[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", "libc", "wasi", "windows-sys 0.52.0", @@ -1966,16 +2150,16 @@ name = "mostro" version = "0.12.8" dependencies = [ "anyhow", - "bitcoin", + "bitcoin 0.32.5", "chrono", "clap", "config", "easy-hasher", "fedimint-tonic-lnd", - "lightning-invoice", + "lightning-invoice 0.32.0", "lnurl-rs", - "mostro-core", - "nostr-sdk", + "mostro-core 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "nostr-sdk 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", "once_cell", "openssl", "reqwest", @@ -1989,6 +2173,48 @@ dependencies = [ "uuid", ] +[[package]] +name = "mostro-cli" +version = "0.10.6" +dependencies = [ + "anyhow", + "bip39", + "bitcoin_hashes 0.15.0", + "chrono", + "clap", + "comfy-table", + "dirs", + "dotenvy", + "lightning-invoice 0.23.0", + "lnurl-rs", + "log", + "mostro-core 0.6.21", + "nostr-sdk 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "openssl", + "pretty_env_logger", + "reqwest", + "sqlx", + "tokio", + "uuid", +] + +[[package]] +name = "mostro-core" +version = "0.6.21" +dependencies = [ + "anyhow", + "bitcoin 0.32.5", + "bitcoin_hashes 0.15.0", + "chrono", + "nostr-sdk 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "serde", + "serde_json", + "sqlx", + "sqlx-crud", + "uuid", + "wasm-bindgen", +] + [[package]] name = "mostro-core" version = "0.6.21" @@ -1996,10 +2222,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52433fda546a12791848792b51980953e66385ff733cbf42df687854315e8f5b" dependencies = [ "anyhow", - "bitcoin", + "bitcoin 0.32.5", "bitcoin_hashes 0.15.0", "chrono", - "nostr-sdk", + "nostr-sdk 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde_json", "sqlx", @@ -2063,7 +2289,32 @@ dependencies = [ "base64 0.22.1", "bech32 0.11.0", "bip39", - "bitcoin", + "bitcoin 0.32.5", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom", + "instant", + "negentropy 0.3.1", + "negentropy 0.4.3", + "once_cell", + "scrypt", + "serde", + "serde_json", + "unicode-normalization", + "url", +] + +[[package]] +name = "nostr" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bech32 0.11.0", + "bip39", + "bitcoin 0.32.5", "cbc", "chacha20", "chacha20poly1305", @@ -2087,43 +2338,82 @@ checksum = "23696338d51e45cd44e061823847f4b0d1d362eca80d5033facf9c184149f72f" dependencies = [ "async-trait", "lru", - "nostr", - "thiserror", + "nostr 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.69", "tokio", "tracing", ] +[[package]] +name = "nostr-database" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-trait", + "nostr 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "tokio", +] + [[package]] name = "nostr-relay-pool" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15fcc6e3f0ca54d0fc779009bc5f2684cea9147be3b6aa68a7d301ea590f95f5" dependencies = [ - "async-utility", - "async-wsocket", - "atomic-destructor", + "async-utility 0.2.0", + "async-wsocket 0.10.1", + "atomic-destructor 0.2.0", "negentropy 0.3.1", "negentropy 0.4.3", - "nostr", - "nostr-database", - "thiserror", + "nostr 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nostr-database 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", ] +[[package]] +name = "nostr-relay-pool" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-utility 0.3.1", + "async-wsocket 0.11.0", + "atomic-destructor 0.3.0", + "negentropy 0.3.1", + "negentropy 0.4.3", + "nostr 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "nostr-database 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "tokio", + "tracing", +] + [[package]] name = "nostr-sdk" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "491221fc89b1aa189a0de640127127d68b4e7c5c1d44371b04d9a6d10694b5af" dependencies = [ - "async-utility", - "atomic-destructor", - "nostr", - "nostr-database", - "nostr-relay-pool", - "thiserror", + "async-utility 0.2.0", + "atomic-destructor 0.2.0", + "nostr 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nostr-database 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nostr-relay-pool 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "nostr-sdk" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-utility 0.3.1", + "nostr 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "nostr-database 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "nostr-relay-pool 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", "tokio", "tracing", ] @@ -2149,9 +2439,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -2197,7 +2487,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -2208,9 +2498,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.4.0+3.4.0" +version = "300.4.1+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" dependencies = [ "cc", ] @@ -2228,6 +2518,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-multimap" version = "0.7.3" @@ -2287,9 +2583,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2311,9 +2607,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pbkdf2" @@ -2333,20 +2629,20 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror", + "thiserror 2.0.9", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -2354,22 +2650,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -2383,7 +2679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -2403,7 +2699,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -2444,6 +2740,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "prettyplease" version = "0.2.25" @@ -2451,14 +2757,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2490,7 +2796,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.87", + "syn 2.0.92", "tempfile", ] @@ -2504,7 +2810,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -2518,9 +2824,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -2566,13 +2872,24 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regex" version = "1.11.1" @@ -2581,7 +2898,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -2596,9 +2913,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2619,21 +2936,21 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "7fe060fe50f524be480214aba758c71f99f90ee8c83c5a36b5e9e1d568eb4eb3" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", "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.5.0", - "hyper-rustls 0.27.3", + "hyper 1.5.2", + "hyper-rustls 0.27.5", "hyper-tls", "hyper-util", "ipnet", @@ -2648,11 +2965,12 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "system-configuration", "tokio", "tokio-native-tls", "tokio-socks", + "tower 0.5.2", "tower-service", "url", "wasm-bindgen", @@ -2721,15 +3039,15 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2758,9 +3076,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring 0.17.8", @@ -2790,9 +3108,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -2817,9 +3135,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -2838,9 +3156,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -2873,6 +3191,16 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "bitcoin_hashes 0.11.0", + "secp256k1-sys 0.6.1", +] + [[package]] name = "secp256k1" version = "0.29.1" @@ -2881,10 +3209,19 @@ checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "bitcoin_hashes 0.14.0", "rand", - "secp256k1-sys", + "secp256k1-sys 0.10.1", "serde", ] +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + [[package]] name = "secp256k1-sys" version = "0.10.1" @@ -2909,9 +3246,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -2919,31 +3256,31 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "memchr", "ryu", @@ -3074,9 +3411,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", @@ -3170,7 +3507,7 @@ dependencies = [ "sqlformat", "sqlx-rt", "stringprep", - "thiserror", + "thiserror 1.0.69", "tokio-stream", "url", "uuid", @@ -3186,7 +3523,7 @@ dependencies = [ "futures", "sqlx", "sqlx-crud-macros", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3198,7 +3535,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3257,6 +3594,25 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.92", +] + [[package]] name = "subtle" version = "2.6.1" @@ -3276,9 +3632,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" dependencies = [ "proc-macro2", "quote", @@ -3293,9 +3649,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", ] @@ -3308,7 +3664,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3334,9 +3690,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -3345,24 +3701,53 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" -version = "1.0.68" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn 2.0.92", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3396,9 +3781,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -3411,9 +3796,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3445,7 +3830,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3481,12 +3866,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.16", - "rustls-pki-types", + "rustls 0.23.20", "tokio", ] @@ -3498,15 +3882,15 @@ checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3521,19 +3905,19 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.16", + "rustls 0.23.20", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tungstenite", - "webpki-roots 0.26.6", + "webpki-roots 0.26.7", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3569,7 +3953,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -3590,7 +3974,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-timeout", "percent-encoding", "pin-project", @@ -3600,7 +3984,7 @@ dependencies = [ "tokio", "tokio-rustls 0.24.1", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -3616,7 +4000,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3639,6 +4023,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tokio", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -3653,9 +4052,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 = [ "log", "pin-project-lite", @@ -3665,20 +4064,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.87", + "syn 2.0.92", ] [[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", "valuable", @@ -3697,9 +4096,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -3728,14 +4127,14 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand", - "rustls 0.23.16", + "rustls 0.23.20", "rustls-pki-types", "sha1 0.10.6", - "thiserror", + "thiserror 1.0.69", "utf-8", ] @@ -3753,15 +4152,15 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -3784,6 +4183,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -3833,9 +4238,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -3888,7 +4293,7 @@ checksum = "6b91f57fe13a38d0ce9e28a03463d8d3c2468ed03d75375110ec71d93b449a08" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] @@ -3926,9 +4331,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -3937,36 +4342,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3974,28 +4379,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4028,9 +4433,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -4051,6 +4456,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4063,7 +4477,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4074,7 +4488,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4083,7 +4497,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4093,7 +4507,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -4102,7 +4525,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4111,7 +4534,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -4120,28 +4558,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4154,24 +4610,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4212,9 +4692,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -4224,13 +4704,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", "synstructure", ] @@ -4252,27 +4732,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", "synstructure", ] @@ -4301,5 +4781,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.92", ] diff --git a/Cargo.toml b/Cargo.toml index a7c0dc33..04036772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,23 +1,18 @@ -[package] -name = "mostro" -version = "0.12.8" -edition = "2021" -license = "MIT" -authors = ["Francisco Calderón "] -description = "Lightning Network peer-to-peer nostr platform" -homepage = "https://mostro.network" -repository = "https://github.com/MostroP2P/mostro" -[[bin]] -name = "mostrod" -path = "src/main.rs" +[workspace] +resolver = "2" -[dependencies] +members = [ + "mostro", + "mostro-cli", + "mostro-core", +] + +[workspace.dependencies] anyhow = "1.0.89" chrono = "0.4.35" -easy-hasher = "2.2.1" +nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = ["nip06", "nip44", "nip59"], rev ="70db575d51965240aab1e1b3f1edab782c0ef625"} lightning-invoice = { version = "0.32.0", features = ["std"] } -nostr-sdk = { version = "0.37.0", features = ["nip59"] } serde = { version = "1.0.210" } serde_json = "1.0.128" sqlx = { version = "0.6.2", features = [ @@ -29,7 +24,6 @@ sqlx = { version = "0.6.2", features = [ "offline", ] } sqlx-crud = { version = "0.4.0", features = ["runtime-tokio-rustls"] } -tokio = { version = "1.40.0", features = ["full"] } fedimint-tonic-lnd = "0.2.0" uuid = { version = "1.8.0", features = [ "v4", diff --git a/mostro-cli/.env-sample b/mostro-cli/.env-sample new file mode 100644 index 00000000..92213911 --- /dev/null +++ b/mostro-cli/.env-sample @@ -0,0 +1,7 @@ +# User private key in nsec format +NSEC_PRIVKEY='nsec1...' +# Mostro pubkey in npub format +MOSTRO_PUBKEY='npub1...' +# Comma-separated list of relays +RELAYS='wss://relay.nostr.vision,wss://nostr.zebedee.cloud,wss://nostr.slothy.win,wss://nostr.rewardsbunny.com,wss://nostr.supremestack.xyz,wss://nostr.shawnyeager.net,wss://relay.nostrmoto.xyz,wss://nostr.roundrockbitcoiners.com' +POW='0' \ No newline at end of file diff --git a/mostro-cli/.github/workflows/rust.yml b/mostro-cli/.github/workflows/rust.yml new file mode 100644 index 00000000..31000a27 --- /dev/null +++ b/mostro-cli/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/mostro-cli/Cargo.lock b/mostro-cli/Cargo.lock new file mode 100644 index 00000000..93cb1aa1 --- /dev/null +++ b/mostro-cli/Cargo.lock @@ -0,0 +1,3727 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-utility" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.11.0" +source = "git+https://github.com/yukibtc/async-wsocket?rev=259c0bc372e7d60d94827b484178bf995afdcbe6#259c0bc372e7d60d94827b484178bf995afdcbe6" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls", + "tokio-socks", + "tokio-tungstenite", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-destructor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals 0.3.0", + "bitcoin_hashes 0.14.0", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bip39" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" +dependencies = [ + "bitcoin_hashes 0.13.0", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +dependencies = [ + "bech32 0.9.1", + "bitcoin_hashes 0.11.0", + "secp256k1 0.24.3", +] + +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32 0.11.0", + "bitcoin-internals 0.3.0", + "bitcoin-io 0.1.3", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative 0.2.1", + "hex_lit", + "secp256k1 0.29.1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b854212e29b96c8f0fe04cab11d57586c8f3257de0d146c76cb3b42b3eb9118" + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26792cd2bf245069a1c5acb06aa7ad7abe1de69b507c90b490bca81e0665d0ee" +dependencies = [ + "bitcoin-internals 0.4.0", +] + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals 0.3.0", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals 0.2.0", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io 0.1.3", + "hex-conservative 0.2.1", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0982261c82a50d89d1a411602afee0498b3e0debe3d36693f0c661352809639" +dependencies = [ + "bitcoin-io 0.2.0", + "hex-conservative 0.3.0", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "comfy-table" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags", + "crossterm_winapi", + "parking_lot", + "rustix", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] + +[[package]] +name = "email_address" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1019fa28f600f5b581b7a603d515c3f1635da041ca211b5055804788673abfe" +dependencies = [ + "serde", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "h2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +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", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls 0.23.20", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +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", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "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]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lightning" +version = "0.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e009e1c0c21f66378b491bb40f548682138c63e09db6f3a05af59f8804bb9f4a" +dependencies = [ + "bitcoin 0.29.2", +] + +[[package]] +name = "lightning-invoice" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e44b0e2822c8811470137d2339fdfe67a699b3248bb1606d1d02eb6a1e9f0a" +dependencies = [ + "bech32 0.9.1", + "bitcoin 0.29.2", + "bitcoin_hashes 0.11.0", + "lightning", + "num-traits", + "secp256k1 0.24.3", +] + +[[package]] +name = "linux-raw-sys" +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 = "lnurl-rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41eacdd87b675792f7752f3dd0937a00241a504c3956c47f72986490662e1db4" +dependencies = [ + "aes", + "anyhow", + "base64 0.22.1", + "bech32 0.11.0", + "bitcoin 0.32.5", + "cbc", + "email_address", + "reqwest", + "serde", + "serde_json", + "ureq", + "url", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "mostro-cli" +version = "0.10.6" +dependencies = [ + "bip39", + "bitcoin_hashes 0.15.0", + "clap", + "comfy-table", + "dirs", + "dotenvy", + "futures", + "lightning-invoice", + "lnurl-rs", + "log", + "mostro-core", + "nostr-sdk", + "openssl", + "pretty_env_logger", + "reqwest", + "sqlx", + "tokio", + "uuid", +] + +[[package]] +name = "mostro-core" +version = "0.6.18" +source = "git+https://github.com/MostroP2P/mostro-core?branch=test-new-sdk#6edf75a4599a7f621f7d47b70bf0a42869a56139" +dependencies = [ + "anyhow", + "bitcoin 0.32.5", + "bitcoin_hashes 0.15.0", + "chrono", + "nostr-sdk", + "serde", + "serde_json", + "uuid", + "wasm-bindgen", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "negentropy" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" + +[[package]] +name = "negentropy" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a88da9dd148bbcdce323dd6ac47d369b4769d4a3b78c6c52389b9269f77932" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nostr" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bech32 0.11.0", + "bip39", + "bitcoin 0.32.5", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom", + "instant", + "negentropy 0.3.1", + "negentropy 0.4.3", + "once_cell", + "scrypt", + "serde", + "serde_json", + "unicode-normalization", + "url", +] + +[[package]] +name = "nostr-database" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-trait", + "nostr", + "tokio", +] + +[[package]] +name = "nostr-relay-pool" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "negentropy 0.3.1", + "negentropy 0.4.3", + "nostr", + "nostr-database", + "tokio", + "tracing", +] + +[[package]] +name = "nostr-sdk" +version = "0.37.0" +source = "git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625#70db575d51965240aab1e1b3f1edab782c0ef625" +dependencies = [ + "async-utility", + "nostr", + "nostr-database", + "nostr-relay-pool", + "tokio", + "tracing", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.4.1+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-socks", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "bitcoin_hashes 0.11.0", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand", + "secp256k1-sys 0.10.1", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.134" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" +dependencies = [ + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.14.5", + "hashlink", + "hex", + "indexmap", + "log", + "memchr", + "native-tls", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "tracing", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.20", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.20", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.26.7", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls 0.23.20", + "rustls-pki-types", + "sha1", + "thiserror", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3" +dependencies = [ + "base64 0.21.7", + "flate2", + "log", + "once_cell", + "rustls 0.21.12", + "rustls-webpki 0.101.7", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.25.4", +] + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", + "rand", + "serde", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b91f57fe13a38d0ce9e28a03463d8d3c2468ed03d75375110ec71d93b449a08" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + +[[package]] +name = "web-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[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 = "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", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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", + "synstructure", +] + +[[package]] +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", +] diff --git a/mostro-cli/Cargo.toml b/mostro-cli/Cargo.toml new file mode 100644 index 00000000..32f0edfc --- /dev/null +++ b/mostro-cli/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "mostro-cli" +version = "0.10.6" +edition = "2021" +license = "MIT" +authors = [ + "Francisco Calderón ", + "Baba O'reily ", +] +description = "Mostro P2P cli client" +homepage = "https://mostro.network" +repository = "https://github.com/MostroP2P/mostro-cli" + +[lib] +name = "mostro_client" +path = "src/lib.rs" + +[[bin]] +name = "mostro-cli" +path = "src/main.rs" + +[dependencies] +anyhow = { workspace = true } +chrono = { workspace = true } +clap = { workspace = true } +nostr-sdk = { workspace = true } +tokio = { version = "1.42.0", features = ["full"] } +comfy-table = "7.0.1" +log = "0.4.17" +uuid = { workspace = true } +dotenvy = "0.15.6" +lightning-invoice = "0.23.0" +reqwest = { version = "0.12.4", features = ["json"] } +mostro-core = { path = "../mostro-core" } +bitcoin_hashes = "0.15.0" +lnurl-rs = "0.9.0" +pretty_env_logger = "0.5.0" +openssl = { version = "0.10.68", features = ["vendored"] } +sqlx = { workspace = true } +bip39 = { version = "2.1.0", features = ["rand"] } +dirs = "5.0.1" diff --git a/mostro-cli/LICENSE b/mostro-cli/LICENSE new file mode 100644 index 00000000..a4897774 --- /dev/null +++ b/mostro-cli/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Francisco Calderón + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mostro-cli/README.md b/mostro-cli/README.md new file mode 100644 index 00000000..ff470247 --- /dev/null +++ b/mostro-cli/README.md @@ -0,0 +1,102 @@ +# Mostro CLI 🧌 + +![Mostro-logo](static/logo.png) + +Very simple command line interface that show all new replaceable events from [Mostro](https://github.com/MostroP2P/mostro) + +## Requirements: + +0. You need Rust version 1.64 or higher to compile. +1. You will need a lightning network node + +## Install dependencies: + +To compile on Ubuntu/Pop!\_OS, please install [cargo](https://www.rust-lang.org/tools/install), then run the following commands: + +``` +$ sudo apt update +$ sudo apt install -y cmake build-essential pkg-config +``` + +## Install + +To install you need to fill the env vars (`.env`) on the with your own private key and add a Mostro pubkey. + +``` +$ git clone https://github.com/MostroP2P/mostro-cli.git +$ cd mostro-cli +$ cp .env-sample .env +$ cargo run +``` + +# Usage + +``` +Commands: + listorders Requests open orders from Mostro pubkey + neworder Create a new buy/sell order on Mostro + takesell Take a sell order from a Mostro pubkey + takebuy Take a buy order from a Mostro pubkey + addinvoice Buyer add a new invoice to receive the payment + getdm Get the latest direct messages from Mostro + fiatsent Send fiat sent message to confirm payment to other user + release Settle the hold invoice and pay to buyer + cancel Cancel a pending order + rate Rate counterpart after a successful trade + dispute Start a dispute + admcancel Cancel an order (only admin) + admsettle Settle a seller's hold invoice (only admin) + admlistdisputes Requests open disputes from Mostro pubkey + admaddsolver Add a new dispute's solver (only admin) + admtakedispute Admin or solver take a Pending dispute (only admin) + help Print this message or the help of the given subcommand(s) + +Options: + -v, --verbose + -n, --nsec + -m, --mostropubkey + -r, --relays + -p, --pow + -h, --help Print help + -V, --version Print version +``` + +# Examples + +``` +$ mostro-cli -m npub1ykvsmrmw2hk7jgxgy64zr8tfkx4nnjhq9eyfxdlg3caha3ph0skq6jr3z0 -n nsec1...5ssky7pw -r 'wss://nos.lol,wss://relay.damus.io,wss://nostr-pub.wellorder.net,wss://nostr.mutinywallet.com,wss://relay.nostr.band,wss://nostr.cizmar.net,wss://140.f7z.io,wss://nostrrelay.com,wss://relay.nostrr.de' listorders + +# You can set the env vars to avoid the -m, -n and -r flags +$ export MOSTROPUBKEY=npub1ykvsmrmw2hk7jgxgy64zr8tfkx4nnjhq9eyfxdlg3caha3ph0skq6jr3z0 +$ export NSEC=nsec1...5ssky7pw +$ export RELAYS='wss://nos.lol,wss://relay.damus.io,wss://nostr-pub.wellorder.net,wss://nostr.mutinywallet.com,wss://relay.nostr.band,wss://nostr.cizmar.net,wss://140.f7z.io,wss://nostrrelay.com,wss://relay.nostrr.de' +$ mostro-cli listorders + +# Create a new buy order +$ mostro-cli neworder -k buy -c ves -f 1000 -m "face to face" + +# Cancel a pending order +$ mostro-cli cancel -o eb5740f6-e584-46c5-953a-29bc3eb818f0 + +# Create a new sell range order with Proof or work difficulty of 10 +$ mostro-cli neworder -p 10 -k sell -c ars -f 1000-10000 -m "face to face" +``` + +## Progress Overview +- [x] Displays order list +- [x] Take orders (Buy & Sell) +- [x] Posts Orders (Buy & Sell) +- [x] Sell flow +- [x] Buy flow +- [x] Maker cancel pending order +- [x] Cooperative cancellation +- [x] Buyer: add new invoice if payment fails +- [x] Rate users +- [x] Dispute flow (users) +- [x] Dispute management (for admins) +- [x] Create buy orders with LN address +- [x] Direct message with peers (use nip-17) +- [x] Conversation key management +- [x] Add a new dispute's solver (for admins) +- [ ] Identity management (Nip-06 support) +- [ ] List own orders diff --git a/archs b/mostro-cli/archs similarity index 100% rename from archs rename to mostro-cli/archs diff --git a/mostro-cli/cross-compile.sh b/mostro-cli/cross-compile.sh new file mode 100755 index 00000000..4aeef713 --- /dev/null +++ b/mostro-cli/cross-compile.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# To make this work you need to have cross installed +# cargo install cross +app="mostro-cli" +file="archs" +manifest="manifest.txt" +arch=`cat $file` +if [ ! -d bin ]; then + mkdir bin +fi +rm bin/* +for i in $arch; do + echo "Cross compiling for $i" + cross build --release --target $i + filename=$app + if [ $i == "x86_64-pc-windows-gnu" ]; then + filename=$filename".exe" + fi + cd target/$i/release + mkdir $i + cp $filename $i/ + sha256sum $i/$filename >> ../../../bin/$manifest + tar -czf $app-$i.tar.gz $i + sha256sum $app-$i.tar.gz >> ../../../bin/$manifest + mv $app-$i.tar.gz ../../../bin + rm -rf $i + cd ../../../ +done \ No newline at end of file diff --git a/rust-toolchain.toml b/mostro-cli/rust-toolchain.toml similarity index 100% rename from rust-toolchain.toml rename to mostro-cli/rust-toolchain.toml diff --git a/mostro-cli/src/cli.rs b/mostro-cli/src/cli.rs new file mode 100644 index 00000000..8a2c8281 --- /dev/null +++ b/mostro-cli/src/cli.rs @@ -0,0 +1,437 @@ +pub mod add_invoice; +pub mod conversation_key; +pub mod get_dm; +pub mod list_disputes; +pub mod list_orders; +pub mod new_order; +pub mod rate_user; +pub mod send_dm; +pub mod send_msg; +pub mod take_buy; +pub mod take_dispute; +pub mod take_sell; + +use crate::cli::add_invoice::execute_add_invoice; +use crate::cli::conversation_key::execute_conversation_key; +use crate::cli::get_dm::execute_get_dm; +use crate::cli::list_disputes::execute_list_disputes; +use crate::cli::list_orders::execute_list_orders; +use crate::cli::new_order::execute_new_order; +use crate::cli::rate_user::execute_rate_user; +use crate::cli::send_dm::execute_send_dm; +use crate::cli::send_msg::execute_send_msg; +use crate::cli::take_buy::execute_take_buy; +use crate::cli::take_dispute::execute_take_dispute; +use crate::cli::take_sell::execute_take_sell; +use crate::db::{connect, User}; +use crate::util; + +use anyhow::{Error, Result}; +use clap::{Parser, Subcommand}; +use nostr_sdk::prelude::*; +use std::{ + env::{set_var, var}, + str::FromStr, +}; +use uuid::Uuid; + +#[derive(Parser)] +#[command( + name = "mostro-cli", + about = "A simple CLI to use Mostro P2P", + author, + help_template = "\ +{before-help}{name} 🧌 + +{about-with-newline} +{author-with-newline} +{usage-heading} {usage} + +{all-args}{after-help} +", + version +)] +#[command(propagate_version = true)] +#[command(arg_required_else_help(true))] +pub struct Cli { + #[command(subcommand)] + pub command: Option, + #[arg(short, long)] + pub verbose: bool, + #[arg(short, long)] + pub nsec: Option, + #[arg(short, long)] + pub mostropubkey: Option, + #[arg(short, long)] + pub relays: Option, + #[arg(short, long)] + pub pow: Option, +} + +#[derive(Subcommand, Clone)] +#[clap(rename_all = "lower")] +pub enum Commands { + /// Requests open orders from Mostro pubkey + ListOrders { + /// Status of the order + #[arg(short, long)] + status: Option, + /// Currency selected + #[arg(short, long)] + currency: Option, + /// Choose an order kind + #[arg(short, long)] + kind: Option, + }, + /// Create a new buy/sell order on Mostro + NewOrder { + /// Choose an order kind + #[arg(short, long)] + kind: String, + /// Sats amount - leave empty for market price + #[arg(short, long)] + #[clap(default_value_t = 0)] + amount: i64, + /// Currency selected + #[arg(short = 'c', long)] + fiat_code: String, + /// Fiat amount + #[arg(short, long)] + #[clap(value_parser=check_fiat_range)] + fiat_amount: (i64, Option), + /// Payment method + #[arg(short = 'm', long)] + payment_method: String, + /// Premium on price + #[arg(short, long)] + #[clap(default_value_t = 0)] + premium: i64, + /// Invoice string + #[arg(short, long)] + invoice: Option, + /// Expiration time of a pending Order, in days + #[arg(short, long)] + #[clap(default_value_t = 0)] + expiration_days: i64, + }, + /// Take a sell order from a Mostro pubkey + TakeSell { + /// Order id + #[arg(short, long)] + order_id: Uuid, + /// Invoice string + #[arg(short, long)] + invoice: Option, + /// Amount of fiat to buy + #[arg(short, long)] + amount: Option, + }, + /// Take a buy order from a Mostro pubkey + TakeBuy { + /// Order id + #[arg(short, long)] + order_id: Uuid, + /// Amount of fiat to sell + #[arg(short, long)] + amount: Option, + }, + /// Buyer add a new invoice to receive the payment + AddInvoice { + /// Order id + #[arg(short, long)] + order_id: Uuid, + /// Invoice string + #[arg(short, long)] + invoice: String, + }, + /// Get the latest direct messages + GetDm { + /// Since time of the messages in minutes + #[arg(short, long)] + #[clap(default_value_t = 30)] + since: i64, + /// If true, get messages from counterparty, otherwise from Mostro + #[arg(short)] + from_user: bool, + }, + /// Send direct message to a user + SendDm { + /// Pubkey of the counterpart + #[arg(short, long)] + pubkey: String, + /// Order id + #[arg(short, long)] + order_id: Uuid, + /// Message to send + #[arg(short, long)] + message: String, + }, + /// Send fiat sent message to confirm payment to other user + FiatSent { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Settle the hold invoice and pay to buyer. + Release { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Cancel a pending order + Cancel { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Rate counterpart after a successful trade + Rate { + /// Order id + #[arg(short, long)] + order_id: Uuid, + /// Rating from 1 to 5 + #[arg(short, long)] + rating: u8, + }, + /// Start a dispute + Dispute { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Cancel an order (only admin) + AdmCancel { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Settle a seller's hold invoice (only admin) + AdmSettle { + /// Order id + #[arg(short, long)] + order_id: Uuid, + }, + /// Requests open disputes from Mostro pubkey + AdmListDisputes {}, + /// Add a new dispute's solver (only admin) + AdmAddSolver { + /// npubkey + #[arg(short, long)] + npubkey: String, + }, + /// Admin or solver take a Pending dispute (only admin) + AdmTakeDispute { + /// Dispute id + #[arg(short, long)] + dispute_id: Uuid, + }, + /// Get the conversation key for direct messaging with a user + ConversationKey { + /// Pubkey of the counterpart + #[arg(short, long)] + pubkey: String, + }, +} + +// Check range with two values value +fn check_fiat_range(s: &str) -> Result<(i64, Option)> { + if s.contains('-') { + let min: i64; + let max: i64; + + // Get values from CLI + let values: Vec<&str> = s.split('-').collect(); + + // Check if more than two values + if values.len() > 2 { + return Err(Error::msg("Wrong amount syntax")); + }; + + // Get ranged command + if let Err(e) = values[0].parse::() { + return Err(e.into()); + } else { + min = values[0].parse().unwrap(); + } + + if let Err(e) = values[1].parse::() { + return Err(e.into()); + } else { + max = values[1].parse().unwrap(); + } + + // Check min below max + if min >= max { + return Err(Error::msg("Range of values must be 100-200 for example...")); + }; + Ok((min, Some(max))) + } else { + match s.parse::() { + Ok(s) => Ok((s, None)), + Err(e) => Err(e.into()), + } + } +} + +pub async fn run() -> Result<()> { + let cli = Cli::parse(); + + // Init logger + if cli.verbose { + set_var("RUST_LOG", "info"); + pretty_env_logger::init(); + } + + if cli.mostropubkey.is_some() { + set_var("MOSTRO_PUBKEY", cli.mostropubkey.unwrap()); + } + let pubkey = var("MOSTRO_PUBKEY").expect("$MOSTRO_PUBKEY env var needs to be set"); + + if cli.nsec.is_some() { + set_var("NSEC_PRIVKEY", cli.nsec.unwrap()); + } + + if cli.relays.is_some() { + set_var("RELAYS", cli.relays.unwrap()); + } + + if cli.pow.is_some() { + set_var("POW", cli.pow.unwrap()); + } + + let pool = connect().await?; + let identity_keys = User::get_identity_keys(&pool) + .await + .map_err(|e| anyhow::anyhow!("Failed to get identity keys: {}", e))?; + + let (trade_keys, trade_index) = User::get_next_trade_keys(&pool) + .await + .map_err(|e| anyhow::anyhow!("Failed to get trade keys: {}", e))?; + // Mostro pubkey + let mostro_key = PublicKey::from_str(&pubkey)?; + + // Call function to connect to relays + let client = util::connect_nostr().await?; + + if let Some(cmd) = cli.command { + match &cmd { + Commands::ConversationKey { pubkey } => { + execute_conversation_key(&trade_keys, PublicKey::from_str(pubkey)?).await? + } + Commands::ListOrders { + status, + currency, + kind, + } => execute_list_orders(kind, currency, status, mostro_key, &client).await?, + Commands::TakeSell { + order_id, + invoice, + amount, + } => { + execute_take_sell( + order_id, + invoice, + *amount, + &identity_keys, + &trade_keys, + trade_index, + mostro_key, + &client, + ) + .await? + } + Commands::TakeBuy { order_id, amount } => { + execute_take_buy( + order_id, + *amount, + &identity_keys, + &trade_keys, + trade_index, + mostro_key, + &client, + ) + .await? + } + Commands::AddInvoice { order_id, invoice } => { + execute_add_invoice(order_id, invoice, &identity_keys, mostro_key, &client).await? + } + Commands::GetDm { since, from_user } => { + execute_get_dm(since, trade_keys, &client, *from_user).await? + } + Commands::FiatSent { order_id } + | Commands::Release { order_id } + | Commands::Dispute { order_id } + | Commands::AdmCancel { order_id } + | Commands::AdmSettle { order_id } + | Commands::Cancel { order_id } => { + execute_send_msg( + cmd.clone(), + Some(*order_id), + Some(&identity_keys), + mostro_key, + &client, + None, + ) + .await? + } + Commands::AdmAddSolver { npubkey } => { + execute_send_msg( + cmd.clone(), + None, + Some(&identity_keys), + mostro_key, + &client, + Some(npubkey), + ) + .await? + } + Commands::NewOrder { + kind, + fiat_code, + amount, + fiat_amount, + payment_method, + premium, + invoice, + expiration_days, + } => { + execute_new_order( + kind, + fiat_code, + fiat_amount, + amount, + payment_method, + premium, + invoice, + &identity_keys, + &trade_keys, + trade_index, + mostro_key, + &client, + expiration_days, + ) + .await? + } + Commands::Rate { order_id, rating } => { + execute_rate_user(order_id, rating, &identity_keys, mostro_key, &client).await?; + } + Commands::AdmTakeDispute { dispute_id } => { + execute_take_dispute(dispute_id, &identity_keys, &trade_keys, mostro_key, &client) + .await? + } + Commands::AdmListDisputes {} => execute_list_disputes(mostro_key, &client).await?, + Commands::SendDm { + pubkey, + order_id, + message, + } => { + let pubkey = PublicKey::from_str(pubkey)?; + execute_send_dm(pubkey, &client, order_id, message).await? + } + }; + } + + println!("Bye Bye!"); + + Ok(()) +} diff --git a/mostro-cli/src/cli/add_invoice.rs b/mostro-cli/src/cli/add_invoice.rs new file mode 100644 index 00000000..82584222 --- /dev/null +++ b/mostro-cli/src/cli/add_invoice.rs @@ -0,0 +1,81 @@ +use crate::db::connect; +use crate::util::send_message_sync; +use crate::{db::Order, lightning::is_valid_invoice}; +use anyhow::Result; +use lnurl::lightning_address::LightningAddress; +use mostro_core::message::{Action, Message, Payload}; +use mostro_core::order::Status; +use nostr_sdk::prelude::*; +use std::str::FromStr; +use uuid::Uuid; + +pub async fn execute_add_invoice( + order_id: &Uuid, + invoice: &str, + identity_keys: &Keys, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + let pool = connect().await?; + let mut order = Order::get_by_id(&pool, &order_id.to_string()).await?; + let trade_keys = order + .trade_keys + .clone() + .ok_or(anyhow::anyhow!("Missing trade keys"))?; + let trade_keys = Keys::parse(&trade_keys)?; + + println!( + "Sending a lightning invoice {} to mostro pubId {}", + order_id, mostro_key + ); + // Check invoice string + let ln_addr = LightningAddress::from_str(invoice); + let payload = if ln_addr.is_ok() { + Some(Payload::PaymentRequest(None, invoice.to_string(), None)) + } else { + match is_valid_invoice(invoice) { + Ok(i) => Some(Payload::PaymentRequest(None, i.to_string(), None)), + Err(e) => { + println!("Invalid invoice: {}", e); + None + } + } + }; + let request_id = Uuid::new_v4().as_u128() as u64; + // Create AddInvoice message + let add_invoice_message = Message::new_order( + Some(*order_id), + Some(request_id), + None, + Action::AddInvoice, + payload, + ); + + let dm = send_message_sync( + client, + Some(identity_keys), + &trade_keys, + mostro_key, + add_invoice_message, + true, + false, + ) + .await?; + + dm.iter().for_each(|el| { + let message = el.0.get_inner_message_kind(); + if message.request_id == Some(request_id) && message.action == Action::WaitingSellerToPay { + println!("Now we should wait for the seller to pay the invoice"); + } + }); + match order + .set_status(Status::WaitingPayment.to_string()) + .save(&pool) + .await + { + Ok(_) => println!("Order status updated"), + Err(e) => println!("Failed to update order status: {}", e), + } + + Ok(()) +} diff --git a/mostro-cli/src/cli/conversation_key.rs b/mostro-cli/src/cli/conversation_key.rs new file mode 100644 index 00000000..1f7a894f --- /dev/null +++ b/mostro-cli/src/cli/conversation_key.rs @@ -0,0 +1,17 @@ +use anyhow::Result; +use nip44::v2::ConversationKey; +use nostr_sdk::prelude::*; + +pub async fn execute_conversation_key(trade_keys: &Keys, receiver: PublicKey) -> Result<()> { + // Derive conversation key + let ck = ConversationKey::derive(trade_keys.secret_key(), &receiver); + let key = ck.as_bytes(); + let mut ck_hex = vec![]; + for i in key { + ck_hex.push(format!("{:02x}", i)); + } + let ck_hex = ck_hex.join(""); + println!("Conversation key: {:?}", ck_hex); + + Ok(()) +} diff --git a/mostro-cli/src/cli/get_dm.rs b/mostro-cli/src/cli/get_dm.rs new file mode 100644 index 00000000..ed2c8989 --- /dev/null +++ b/mostro-cli/src/cli/get_dm.rs @@ -0,0 +1,72 @@ +use std::collections::HashSet; + +use anyhow::Result; +use chrono::DateTime; +use mostro_core::message::{Message, Payload}; +use nostr_sdk::prelude::*; + +use crate::{ + db::{connect, Order}, + util::get_direct_messages, +}; + +pub async fn execute_get_dm( + since: &i64, + trade_keys: Keys, + client: &Client, + from_user: bool, +) -> Result<()> { + let mut dm: Vec<(Message, u64)> = Vec::new(); + let pool = connect().await?; + let orders = Order::get_all(&pool).await.unwrap(); + let trade_keys_hex = trade_keys.secret_key().to_secret_hex(); + let order_trade_keys = orders + .iter() + .filter_map(|order| order.trade_keys.as_ref().cloned()) + .collect::>(); + let mut unique_trade_keys = order_trade_keys + .iter() + .cloned() + .collect::>(); + unique_trade_keys.insert(trade_keys_hex); + let final_trade_keys = unique_trade_keys.iter().cloned().collect::>(); + for keys in final_trade_keys.iter() { + let trade_keys = + Keys::parse(keys).map_err(|e| anyhow::anyhow!("Failed to parse trade keys: {}", e))?; + let dm_temp = get_direct_messages(client, &trade_keys, *since, from_user).await; + dm.extend(dm_temp); + } + + if dm.is_empty() { + println!(); + println!("No new messages"); + println!(); + } else { + for m in dm.iter() { + let date = DateTime::from_timestamp(m.1 as i64, 0).unwrap(); + if m.0.get_inner_message_kind().id.is_some() { + println!( + "Mostro sent you this message for order id: {} at {}", + m.0.get_inner_message_kind().id.unwrap(), + date + ); + } + if let Some(Payload::PaymentRequest(_, inv, _)) = &m.0.get_inner_message_kind().payload + { + println!(); + println!("Pay this invoice to continue --> {}", inv); + println!(); + } else if let Some(Payload::TextMessage(text)) = &m.0.get_inner_message_kind().payload { + println!(); + println!("{text}"); + println!(); + } else { + println!(); + println!("Action: {}", m.0.get_inner_message_kind().action); + println!("Payload: {:#?}", m.0.get_inner_message_kind().payload); + println!(); + } + } + } + Ok(()) +} diff --git a/mostro-cli/src/cli/list_disputes.rs b/mostro-cli/src/cli/list_disputes.rs new file mode 100644 index 00000000..6951647c --- /dev/null +++ b/mostro-cli/src/cli/list_disputes.rs @@ -0,0 +1,19 @@ +use anyhow::Result; +use nostr_sdk::prelude::*; + +use crate::pretty_table::print_disputes_table; +use crate::util::get_disputes_list; + +pub async fn execute_list_disputes(mostro_key: PublicKey, client: &Client) -> Result<()> { + println!( + "Requesting disputes from mostro pubId - {}", + mostro_key.clone() + ); + + // Get orders from relays + let table_of_disputes = get_disputes_list(mostro_key, client).await?; + let table = print_disputes_table(table_of_disputes)?; + println!("{table}"); + + Ok(()) +} diff --git a/mostro-cli/src/cli/list_orders.rs b/mostro-cli/src/cli/list_orders.rs new file mode 100644 index 00000000..ee8d8d6f --- /dev/null +++ b/mostro-cli/src/cli/list_orders.rs @@ -0,0 +1,63 @@ +use anyhow::Result; +use mostro_core::order::{Kind, Status}; +use nostr_sdk::prelude::*; +use std::str::FromStr; + +use crate::pretty_table::print_orders_table; +use crate::util::get_orders_list; + +pub async fn execute_list_orders( + kind: &Option, + currency: &Option, + status: &Option, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + // Used to get upper currency string to check against a list of tickers + let mut upper_currency: Option = None; + let mut status_checked: Option = Some(Status::from_str("pending").unwrap()); + let mut kind_checked: Option = None; + + // New check against strings + if let Some(s) = status { + status_checked = Some(Status::from_str(s).expect("Not valid status! Please check")); + } + + println!( + "You are searching orders with status {:?}", + status_checked.unwrap() + ); + // New check against strings + if let Some(k) = kind { + kind_checked = Some(Kind::from_str(k).expect("Not valid order kind! Please check")); + println!("You are searching {} orders", kind_checked.unwrap()); + } + + // Uppercase currency + if let Some(curr) = currency { + upper_currency = Some(curr.to_uppercase()); + println!( + "You are searching orders with currency {}", + upper_currency.clone().unwrap() + ); + } + + println!( + "Requesting orders from mostro pubId - {}", + mostro_key.clone() + ); + + // Get orders from relays + let table_of_orders = get_orders_list( + mostro_key, + status_checked.unwrap(), + upper_currency, + kind_checked, + client, + ) + .await?; + let table = print_orders_table(table_of_orders)?; + println!("{table}"); + + Ok(()) +} diff --git a/mostro-cli/src/cli/new_order.rs b/mostro-cli/src/cli/new_order.rs new file mode 100644 index 00000000..39bd6d95 --- /dev/null +++ b/mostro-cli/src/cli/new_order.rs @@ -0,0 +1,188 @@ +use anyhow::Result; +use mostro_core::message::{Action, Message, Payload}; +use mostro_core::order::SmallOrder; +use mostro_core::order::{Kind, Status}; +use nostr_sdk::prelude::*; +use std::collections::HashMap; +use std::io::{stdin, stdout, BufRead, Write}; +use std::process; +use std::str::FromStr; +use uuid::Uuid; + +use crate::db::{connect, Order, User}; +use crate::pretty_table::print_order_preview; +use crate::util::{send_message_sync, uppercase_first}; + +pub type FiatNames = HashMap; + +#[allow(clippy::too_many_arguments)] +pub async fn execute_new_order( + kind: &str, + fiat_code: &str, + fiat_amount: &(i64, Option), + amount: &i64, + payment_method: &String, + premium: &i64, + invoice: &Option, + identity_keys: &Keys, + trade_keys: &Keys, + trade_index: i64, + mostro_key: PublicKey, + client: &Client, + expiration_days: &i64, +) -> Result<()> { + // Uppercase currency + let fiat_code = fiat_code.to_uppercase(); + // Check if fiat currency selected is available on Yadio and eventually force user to set amount + // this is in the case of crypto <--> crypto offer for example + if *amount == 0 { + // Get Fiat list + let api_req_string = "https://api.yadio.io/currencies".to_string(); + let fiat_list_check = reqwest::get(api_req_string) + .await? + .json::() + .await? + .contains_key(&fiat_code); + if !fiat_list_check { + println!("{} is not present in the fiat market, please specify an amount with -a flag to fix the rate", fiat_code); + process::exit(0); + } + } + let kind = uppercase_first(kind); + // New check against strings + let kind_checked = Kind::from_str(&kind).unwrap(); + let expires_at = match *expiration_days { + 0 => None, + _ => { + let now = chrono::Utc::now(); + let expires_at = now + chrono::Duration::days(*expiration_days); + Some(expires_at.timestamp()) + } + }; + + // Get the type of neworder + // if both tuple field are valid than it's a range order + // otherwise use just fiat amount value as before + let amt = if fiat_amount.1.is_some() { + (0, Some(fiat_amount.0), fiat_amount.1) + } else { + (fiat_amount.0, None, None) + }; + let small_order = SmallOrder::new( + None, + Some(kind_checked), + Some(Status::Pending), + *amount, + fiat_code.clone(), + amt.1, + amt.2, + amt.0, + payment_method.to_owned(), + *premium, + None, + None, + invoice.as_ref().to_owned().cloned(), + Some(0), + expires_at, + None, + None, + ); + + // Create new order for mostro + let order_content = Payload::Order(small_order.clone()); + + // Print order preview + let ord_preview = print_order_preview(order_content.clone()).unwrap(); + println!("{ord_preview}"); + let mut user_input = String::new(); + let _input = stdin(); + print!("Check your order! Is it correct? (Y/n) > "); + stdout().flush()?; + + let mut answer = stdin().lock(); + answer.read_line(&mut user_input)?; + + match user_input.to_lowercase().as_str().trim_end() { + "y" | "" => {} + "n" => { + println!("Ok you have cancelled the order, create another one please"); + process::exit(0); + } + &_ => { + println!("Can't get what you're sayin!"); + process::exit(0); + } + }; + let request_id = Uuid::new_v4().as_u128() as u64; + // Create NewOrder message + let message = Message::new_order( + None, + Some(request_id), + Some(trade_index), + Action::NewOrder, + Some(order_content), + ); + + let dm = send_message_sync( + client, + Some(identity_keys), + trade_keys, + mostro_key, + message, + true, + false, + ) + .await?; + let order_id = dm + .iter() + .find_map(|el| { + let message = el.0.get_inner_message_kind(); + if message.request_id == Some(request_id) { + match message.action { + Action::NewOrder => { + if let Some(Payload::Order(order)) = message.payload.as_ref() { + return order.id; + } + } + Action::OutOfRangeFiatAmount | Action::OutOfRangeSatsAmount => { + println!("Error: Amount is outside the allowed range. Please check the order's min/max limits."); + return None; + } + _ => { + println!("Unknown action: {:?}", message.action); + return None; + } + } + } + None + }) + .or_else(|| { + println!("Error: No matching order found in response"); + None + }); + + if let Some(order_id) = order_id { + println!("Order id {} created", order_id); + // Create order in db + let pool = connect().await?; + let db_order = Order::new(&pool, small_order, trade_keys, Some(request_id as i64)) + .await + .map_err(|e| anyhow::anyhow!("Failed to create DB order: {:?}", e))?; + // Update last trade index + match User::get(&pool).await { + Ok(mut user) => { + user.set_last_trade_index(trade_index + 1); + if let Err(e) = user.save(&pool).await { + println!("Failed to update user: {}", e); + } + } + Err(e) => println!("Failed to get user: {}", e), + } + let db_order_id = db_order + .id + .clone() + .ok_or(anyhow::anyhow!("Missing order id"))?; + Order::save_new_id(&pool, db_order_id, order_id.to_string()).await?; + } + Ok(()) +} diff --git a/mostro-cli/src/cli/rate_user.rs b/mostro-cli/src/cli/rate_user.rs new file mode 100644 index 00000000..146040f0 --- /dev/null +++ b/mostro-cli/src/cli/rate_user.rs @@ -0,0 +1,65 @@ +use anyhow::Result; +use mostro_core::message::{Action, Message, Payload}; +use nostr_sdk::prelude::*; +use uuid::Uuid; + +use crate::{ + db::{connect, Order}, + util::send_message_sync, +}; + +pub async fn execute_rate_user( + order_id: &Uuid, + rating: &u8, + identity_keys: &Keys, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + // User rating + let rating_content; + + // Check boundaries + if let 1..=5 = *rating { + rating_content = Payload::RatingUser(*rating); + } else { + println!("Rating must be in the range 1 - 5"); + std::process::exit(0); + } + + let pool = connect().await?; + + let trade_keys = if let Ok(order_to_vote) = Order::get_by_id(&pool, &order_id.to_string()).await + { + match order_to_vote.trade_keys.as_ref() { + Some(trade_keys) => Keys::parse(trade_keys)?, + None => { + anyhow::bail!("No trade_keys found for this order"); + } + } + } else { + println!("order {} not found", order_id); + std::process::exit(0) + }; + + // Create rating message of counterpart + let rate_message = Message::new_order( + Some(*order_id), + None, + None, + Action::RateUser, + Some(rating_content), + ); + + send_message_sync( + client, + Some(identity_keys), + &trade_keys, + mostro_key, + rate_message, + true, + false, + ) + .await?; + + std::process::exit(0); +} diff --git a/mostro-cli/src/cli/send_dm.rs b/mostro-cli/src/cli/send_dm.rs new file mode 100644 index 00000000..645e3040 --- /dev/null +++ b/mostro-cli/src/cli/send_dm.rs @@ -0,0 +1,39 @@ +use crate::{db::Order, util::send_message_sync}; +use anyhow::Result; +use mostro_core::message::{Action, Message, Payload}; +use nostr_sdk::prelude::*; +use uuid::Uuid; + +pub async fn execute_send_dm( + receiver: PublicKey, + client: &Client, + order_id: &Uuid, + message: &str, +) -> Result<()> { + let message = Message::new_dm( + None, + None, + Action::SendDm, + Some(Payload::TextMessage(message.to_string())), + ); + + let pool = crate::db::connect().await?; + + let trade_keys = if let Ok(order_to_vote) = Order::get_by_id(&pool, &order_id.to_string()).await + { + match order_to_vote.trade_keys.as_ref() { + Some(trade_keys) => Keys::parse(trade_keys)?, + None => { + anyhow::bail!("No trade_keys found for this order"); + } + } + } else { + println!("order {} not found", order_id); + std::process::exit(0) + }; + + + send_message_sync(client, None, &trade_keys, receiver, message, true, true).await?; + + Ok(()) +} diff --git a/mostro-cli/src/cli/send_msg.rs b/mostro-cli/src/cli/send_msg.rs new file mode 100644 index 00000000..a628cd3c --- /dev/null +++ b/mostro-cli/src/cli/send_msg.rs @@ -0,0 +1,76 @@ +use crate::db::Order; +use crate::util::send_message_sync; +use crate::{cli::Commands, db::connect}; + +use anyhow::Result; +use log::info; +use mostro_core::message::{Action, Message, Payload}; +use nostr_sdk::prelude::*; +use std::process; +use uuid::Uuid; + +pub async fn execute_send_msg( + command: Commands, + order_id: Option, + identity_keys: Option<&Keys>, + mostro_key: PublicKey, + client: &Client, + text: Option<&str>, +) -> Result<()> { + // Get desised action based on command from CLI + let requested_action = match command { + Commands::FiatSent { order_id: _ } => Action::FiatSent, + Commands::Release { order_id: _ } => Action::Release, + Commands::Cancel { order_id: _ } => Action::Cancel, + Commands::Dispute { order_id: _ } => Action::Dispute, + Commands::AdmCancel { order_id: _ } => Action::AdminCancel, + Commands::AdmSettle { order_id: _ } => Action::AdminSettle, + Commands::AdmAddSolver { npubkey: _ } => Action::AdminAddSolver, + _ => { + println!("Not a valid command!"); + process::exit(0); + } + }; + + println!( + "Sending {} command for order {:?} to mostro pubId {}", + requested_action, + order_id, + mostro_key.clone() + ); + let mut payload = None; + if let Some(t) = text { + payload = Some(Payload::TextMessage(t.to_string())); + } + + // Create message + let message = Message::new_order(order_id, None, None, requested_action, payload); + info!("Sending message: {:#?}", message); + + let pool = connect().await?; + let order = Order::get_by_id(&pool, &order_id.unwrap().to_string()).await; + match order { + Ok(order) => { + if let Some(trade_keys_str) = order.trade_keys { + let trade_keys = Keys::parse(&trade_keys_str)?; + send_message_sync( + client, + identity_keys, + &trade_keys, + mostro_key, + message, + false, + false, + ) + .await?; + } else { + println!("Error: Missing trade keys for order {}", order_id.unwrap()); + } + } + Err(e) => { + println!("Error: {}", e); + } + } + + Ok(()) +} diff --git a/mostro-cli/src/cli/take_buy.rs b/mostro-cli/src/cli/take_buy.rs new file mode 100644 index 00000000..f525e208 --- /dev/null +++ b/mostro-cli/src/cli/take_buy.rs @@ -0,0 +1,100 @@ +use anyhow::Result; +use mostro_core::message::{Action, Message, Payload}; +use nostr_sdk::prelude::*; +use uuid::Uuid; + +use crate::{ + db::{connect, Order, User}, + util::send_message_sync, +}; + +pub async fn execute_take_buy( + order_id: &Uuid, + amount: Option, + identity_keys: &Keys, + trade_keys: &Keys, + trade_index: i64, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + println!( + "Request of take buy order {} from mostro pubId {}", + order_id, + mostro_key.clone() + ); + let request_id = Uuid::new_v4().as_u128() as u64; + let payload = amount.map(|amt: u32| Payload::Amount(amt as i64)); + // Create takebuy message + let take_buy_message = Message::new_order( + Some(*order_id), + Some(request_id), + Some(trade_index), + Action::TakeBuy, + payload, + ); + + let dm = send_message_sync( + client, + Some(identity_keys), + trade_keys, + mostro_key, + take_buy_message, + true, + false, + ) + .await?; + + let pool = connect().await?; + + let order = dm.iter().find_map(|el| { + let message = el.0.get_inner_message_kind(); + if message.request_id == Some(request_id) { + match message.action { + Action::PayInvoice => { + if let Some(Payload::PaymentRequest(order, invoice, _)) = &message.payload { + println!( + "Mostro sent you this hold invoice for order id: {}", + order + .as_ref() + .and_then(|o| o.id) + .map_or("unknown".to_string(), |id| id.to_string()) + ); + println!(); + println!("Pay this invoice to continue --> {}", invoice); + println!(); + return order.clone(); + } + } + Action::OutOfRangeFiatAmount | Action::OutOfRangeSatsAmount=> { + println!("Error: Amount is outside the allowed range. Please check the order's min/max limits."); + return None; + } + _ => { + println!("Unknown action: {:?}", message.action); + return None; + } + } + } + None + }); + if let Some(o) = order { + match Order::new(&pool, o, trade_keys, Some(request_id as i64)).await { + Ok(order) => { + println!("Order {} created", order.id.unwrap()); + // Update last trade index to be used in next trade + match User::get(&pool).await { + Ok(mut user) => { + user.set_last_trade_index(trade_index + 1); + if let Err(e) = user.save(&pool).await { + println!("Failed to update user: {}", e); + } + } + Err(e) => println!("Failed to get user: {}", e), + } + } + Err(e) => println!("{}", e), + } + } + + Ok(()) +} diff --git a/mostro-cli/src/cli/take_dispute.rs b/mostro-cli/src/cli/take_dispute.rs new file mode 100644 index 00000000..5189baf8 --- /dev/null +++ b/mostro-cli/src/cli/take_dispute.rs @@ -0,0 +1,41 @@ +use anyhow::Result; +use mostro_core::message::{Action, Message}; +use nostr_sdk::prelude::*; +use uuid::Uuid; + +use crate::util::send_message_sync; + +pub async fn execute_take_dispute( + dispute_id: &Uuid, + identity_keys: &Keys, + trade_keys: &Keys, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + println!( + "Request of take dispute {} from mostro pubId {}", + dispute_id, + mostro_key.clone() + ); + // Create takebuy message + let take_dispute_message = Message::new_dispute( + Some(*dispute_id), + None, + None, + Action::AdminTakeDispute, + None, + ); + + send_message_sync( + client, + Some(identity_keys), + trade_keys, + mostro_key, + take_dispute_message, + true, + false, + ) + .await?; + + Ok(()) +} diff --git a/mostro-cli/src/cli/take_sell.rs b/mostro-cli/src/cli/take_sell.rs new file mode 100644 index 00000000..dcc153d9 --- /dev/null +++ b/mostro-cli/src/cli/take_sell.rs @@ -0,0 +1,123 @@ +use anyhow::Result; +use lnurl::lightning_address::LightningAddress; +use mostro_core::message::{Action, Message, Payload}; +use nostr_sdk::prelude::*; +use std::str::FromStr; +use uuid::Uuid; + +use crate::db::{connect, Order, User}; +use crate::lightning::is_valid_invoice; +use crate::util::send_message_sync; + +#[allow(clippy::too_many_arguments)] +pub async fn execute_take_sell( + order_id: &Uuid, + invoice: &Option, + amount: Option, + identity_keys: &Keys, + trade_keys: &Keys, + trade_index: i64, + mostro_key: PublicKey, + client: &Client, +) -> Result<()> { + println!( + "Request of take sell order {} from mostro pubId {}", + order_id, + mostro_key.clone() + ); + let mut payload = None; + if let Some(invoice) = invoice { + // Check invoice string + let ln_addr = LightningAddress::from_str(invoice); + if ln_addr.is_ok() { + payload = Some(Payload::PaymentRequest(None, invoice.to_string(), None)); + } else { + match is_valid_invoice(invoice) { + Ok(i) => payload = Some(Payload::PaymentRequest(None, i.to_string(), None)), + Err(e) => println!("{}", e), + } + } + } + + // Add amount in case it's specified + if amount.is_some() { + payload = match payload { + Some(Payload::PaymentRequest(a, b, _)) => { + Some(Payload::PaymentRequest(a, b, Some(amount.unwrap() as i64))) + } + None => Some(Payload::Amount(amount.unwrap().into())), + _ => None, + }; + } + let request_id = Uuid::new_v4().as_u128() as u64; + // Create takesell message + let take_sell_message = Message::new_order( + Some(*order_id), + Some(request_id), + Some(trade_index), + Action::TakeSell, + payload, + ); + + let dm = send_message_sync( + client, + Some(identity_keys), + trade_keys, + mostro_key, + take_sell_message, + true, + false, + ) + .await?; + let pool = connect().await?; + + let order = dm.iter().find_map(|el| { + let message = el.0.get_inner_message_kind(); + if message.request_id == Some(request_id) { + match message.action { + Action::AddInvoice => { + if let Some(Payload::Order(order)) = message.payload.as_ref() { + println!( + "Please add a lightning invoice with amount of {}", + order.amount + ); + return Some(order.clone()); + } + } + Action::OutOfRangeFiatAmount | Action::OutOfRangeSatsAmount => { + println!("Error: Amount is outside the allowed range. Please check the order's min/max limits."); + return None; + } + _ => { + println!("Unknown action: {:?}", message.action); + return None; + } + } + } + None + }); + if let Some(o) = order { + match Order::new(&pool, o, trade_keys, Some(request_id as i64)).await { + Ok(order) => { + if let Some(order_id) = order.id { + println!("Order {} created", order_id); + } else { + println!("Warning: The newly created order has no ID."); + } + // Update last trade index to be used in next trade + match User::get(&pool).await { + Ok(mut user) => { + user.set_last_trade_index(trade_index + 1); + if let Err(e) = user.save(&pool).await { + println!("Failed to update user: {}", e); + } + } + Err(e) => println!("Failed to get user: {}", e), + } + } + Err(e) => println!("{}", e), + } + } + + Ok(()) +} diff --git a/mostro-cli/src/db.rs b/mostro-cli/src/db.rs new file mode 100644 index 00000000..57da15d6 --- /dev/null +++ b/mostro-cli/src/db.rs @@ -0,0 +1,433 @@ +use crate::util::get_mcli_path; +use anyhow::Result; +use mostro_core::order::SmallOrder; +use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND; +use nip06::FromMnemonic; +use nostr_sdk::prelude::*; +use sqlx::pool::Pool; +use sqlx::Sqlite; +use sqlx::SqlitePool; +use std::fs::File; +use std::path::Path; + +pub async fn connect() -> Result> { + let mcli_dir = get_mcli_path(); + let mcli_db_path = format!("{}/mcli.db", mcli_dir); + let db_url = format!("sqlite://{}", mcli_db_path); + let pool: Pool; + if !Path::exists(Path::new(&mcli_db_path)) { + if let Err(res) = File::create(&mcli_db_path) { + println!("Error in creating db file: {}", res); + return Err(res.into()); + } + pool = SqlitePool::connect(&db_url).await?; + println!("Creating database file with orders table..."); + sqlx::query( + r#" + CREATE TABLE IF NOT EXISTS orders ( + id TEXT PRIMARY KEY, + kind TEXT NOT NULL, + status TEXT NOT NULL, + amount INTEGER NOT NULL, + min_amount INTEGER, + max_amount INTEGER, + fiat_code TEXT NOT NULL, + fiat_amount INTEGER NOT NULL, + payment_method TEXT NOT NULL, + premium INTEGER NOT NULL, + trade_keys TEXT, + counterparty_pubkey TEXT, + is_mine BOOLEAN, + buyer_invoice TEXT, + buyer_token INTEGER, + seller_token INTEGER, + request_id INTEGER, + created_at INTEGER, + expires_at INTEGER + ); + CREATE TABLE IF NOT EXISTS users ( + i0_pubkey char(64) PRIMARY KEY, + mnemonic TEXT, + last_trade_index INTEGER, + created_at INTEGER + ); + "#, + ) + .execute(&pool) + .await?; + + let mnemonic = match Mnemonic::generate(12) { + Ok(m) => m.to_string(), + Err(e) => { + println!("Error generating mnemonic: {}", e); + return Err(e.into()); + } + }; + let user = User::new(mnemonic, &pool).await?; + println!("User created with pubkey: {}", user.i0_pubkey); + } else { + pool = SqlitePool::connect(&db_url).await?; + } + + Ok(pool) +} + +#[derive(Debug, Default, Clone, sqlx::FromRow)] +pub struct User { + /// The user's ID is the identity pubkey + pub i0_pubkey: String, + pub mnemonic: String, + pub last_trade_index: Option, + pub created_at: i64, +} + +impl User { + pub async fn new(mnemonic: String, pool: &SqlitePool) -> Result { + let mut user = User::default(); + let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; + let i0_keys = + Keys::from_mnemonic_advanced(&mnemonic, None, Some(account), Some(0), Some(0))?; + user.i0_pubkey = i0_keys.public_key().to_string(); + user.created_at = chrono::Utc::now().timestamp(); + user.mnemonic = mnemonic; + sqlx::query( + r#" + INSERT INTO users (i0_pubkey, mnemonic, created_at) + VALUES (?, ?, ?) + "#, + ) + .bind(&user.i0_pubkey) + .bind(&user.mnemonic) + .bind(user.created_at) + .execute(pool) + .await?; + + Ok(user) + } + // Chainable setters + pub fn set_mnemonic(&mut self, mnemonic: String) -> &mut Self { + self.mnemonic = mnemonic; + self + } + + pub fn set_last_trade_index(&mut self, last_trade_index: i64) -> &mut Self { + self.last_trade_index = Some(last_trade_index); + self + } + + // Applying changes to the database + pub async fn save(&self, pool: &SqlitePool) -> Result<()> { + sqlx::query( + r#" + UPDATE users + SET mnemonic = ?, last_trade_index = ? + WHERE i0_pubkey = ? + "#, + ) + .bind(&self.mnemonic) + .bind(self.last_trade_index) + .bind(&self.i0_pubkey) + .execute(pool) + .await?; + + println!( + "User with i0 pubkey {} updated in the database.", + self.i0_pubkey + ); + + Ok(()) + } + + pub async fn get(pool: &SqlitePool) -> Result { + let user = sqlx::query_as::<_, User>( + r#" + SELECT i0_pubkey, mnemonic, last_trade_index, created_at + FROM users + LIMIT 1 + "#, + ) + .fetch_one(pool) + .await?; + + Ok(user) + } + + pub async fn get_next_trade_index(pool: SqlitePool) -> Result { + let user = User::get(&pool).await?; + match user.last_trade_index { + Some(index) => Ok(index + 1), + None => Ok(1), + } + } + + pub async fn get_identity_keys(pool: &SqlitePool) -> Result { + let user = User::get(pool).await?; + let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; + let keys = + Keys::from_mnemonic_advanced(&user.mnemonic, None, Some(account), Some(0), Some(0))?; + + Ok(keys) + } + + pub async fn get_next_trade_keys(pool: &SqlitePool) -> Result<(Keys, i64)> { + let mut trade_index = User::get_next_trade_index(pool.clone()).await?; + trade_index -= 1; + + let user = User::get(pool).await?; + let account = NOSTR_REPLACEABLE_EVENT_KIND as u32; + match trade_index.try_into() { + Ok(index) => { + let keys = Keys::from_mnemonic_advanced( + &user.mnemonic, + None, + Some(account), + Some(0), + Some(index), + )?; + Ok((keys, trade_index)) + } + Err(e) => { + println!("Error: {}", e); + Err(e.into()) + } + } + } +} + +#[derive(Debug, Default, Clone, sqlx::FromRow)] +pub struct Order { + pub id: Option, + pub kind: Option, + pub status: Option, + pub amount: i64, + pub fiat_code: String, + pub min_amount: Option, + pub max_amount: Option, + pub fiat_amount: i64, + pub payment_method: String, + pub premium: i64, + pub trade_keys: Option, + pub counterparty_pubkey: Option, + pub is_mine: Option, + pub buyer_invoice: Option, + pub buyer_token: Option, + pub seller_token: Option, + pub request_id: Option, + pub created_at: Option, + pub expires_at: Option, +} + +impl Order { + pub async fn new( + pool: &SqlitePool, + order: SmallOrder, + trade_keys: &Keys, + request_id: Option, + ) -> Result { + let trade_keys_hex = trade_keys.secret_key().to_secret_hex(); + let id = match order.id { + Some(id) => id.to_string(), + None => uuid::Uuid::new_v4().to_string(), + }; + let order = Order { + id: Some(id), + kind: order.kind.as_ref().map(|k| k.to_string()), + status: order.status.as_ref().map(|s| s.to_string()), + amount: order.amount, + fiat_code: order.fiat_code, + min_amount: order.min_amount, + max_amount: order.max_amount, + fiat_amount: order.fiat_amount, + payment_method: order.payment_method, + premium: order.premium, + trade_keys: Some(trade_keys_hex), + counterparty_pubkey: None, + is_mine: Some(true), + buyer_invoice: None, + buyer_token: None, + seller_token: None, + request_id, + created_at: Some(chrono::Utc::now().timestamp()), + expires_at: None, + }; + + sqlx::query( + r#" + INSERT INTO orders (id, kind, status, amount, min_amount, max_amount, + fiat_code, fiat_amount, payment_method, premium, trade_keys, + counterparty_pubkey, is_mine, buyer_invoice, buyer_token, seller_token, + request_id, created_at, expires_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + "#, + ) + .bind(&order.id) + .bind(&order.kind) + .bind(&order.status) + .bind(order.amount) + .bind(order.min_amount) + .bind(order.max_amount) + .bind(&order.fiat_code) + .bind(order.fiat_amount) + .bind(&order.payment_method) + .bind(order.premium) + .bind(&order.trade_keys) + .bind(&order.counterparty_pubkey) + .bind(order.is_mine) + .bind(&order.buyer_invoice) + .bind(order.buyer_token) + .bind(order.seller_token) + .bind(order.request_id) + .bind(order.created_at) + .bind(order.expires_at) + .execute(pool) + .await?; + + Ok(order) + } + + // Setters encadenables + pub fn set_kind(&mut self, kind: String) -> &mut Self { + self.kind = Some(kind); + self + } + + pub fn set_status(&mut self, status: String) -> &mut Self { + self.status = Some(status); + self + } + + pub fn set_amount(&mut self, amount: i64) -> &mut Self { + self.amount = amount; + self + } + + pub fn set_fiat_code(&mut self, fiat_code: String) -> &mut Self { + self.fiat_code = fiat_code; + self + } + + pub fn set_min_amount(&mut self, min_amount: i64) -> &mut Self { + self.min_amount = Some(min_amount); + self + } + + pub fn set_max_amount(&mut self, max_amount: i64) -> &mut Self { + self.max_amount = Some(max_amount); + self + } + + pub fn set_fiat_amount(&mut self, fiat_amount: i64) -> &mut Self { + self.fiat_amount = fiat_amount; + self + } + + pub fn set_payment_method(&mut self, payment_method: String) -> &mut Self { + self.payment_method = payment_method; + self + } + + pub fn set_premium(&mut self, premium: i64) -> &mut Self { + self.premium = premium; + self + } + + pub fn set_counterparty_pubkey(&mut self, counterparty_pubkey: String) -> &mut Self { + self.counterparty_pubkey = Some(counterparty_pubkey); + self + } + + pub fn set_trade_keys(&mut self, trade_keys: String) -> &mut Self { + self.trade_keys = Some(trade_keys); + self + } + + pub fn set_is_mine(&mut self, is_mine: bool) -> &mut Self { + self.is_mine = Some(is_mine); + self + } + + // Applying changes to the database + pub async fn save(&self, pool: &SqlitePool) -> Result<()> { + // Validation if an identity document is present + if let Some(ref id) = self.id { + sqlx::query( + r#" + UPDATE orders + SET kind = ?, status = ?, amount = ?, fiat_code = ?, min_amount = ?, max_amount = ?, + fiat_amount = ?, payment_method = ?, premium = ?, trade_keys = ?, counterparty_pubkey = ?, + is_mine = ?, buyer_invoice = ?, created_at = ?, expires_at = ?, buyer_token = ?, + seller_token = ? + WHERE id = ? + "#, + ) + .bind(&self.kind) + .bind(&self.status) + .bind(self.amount) + .bind(&self.fiat_code) + .bind(self.min_amount) + .bind(self.max_amount) + .bind(self.fiat_amount) + .bind(&self.payment_method) + .bind(self.premium) + .bind(&self.trade_keys) + .bind(&self.counterparty_pubkey) + .bind(self.is_mine) + .bind(&self.buyer_invoice) + .bind(self.created_at) + .bind(self.expires_at) + .bind(self.buyer_token) + .bind(self.seller_token) + .bind(id) + .execute(pool) + .await?; + + println!("Order with id {} updated in the database.", id); + } else { + return Err(anyhow::anyhow!("Order must have an ID to be updated.")); + } + + Ok(()) + } + + pub async fn save_new_id( + pool: &SqlitePool, + id: String, + new_id: String, + ) -> anyhow::Result { + let rows_affected = sqlx::query( + r#" + UPDATE orders + SET id = ? + WHERE id = ? + "#, + ) + .bind(&new_id) + .bind(&id) + .execute(pool) + .await? + .rows_affected(); + + Ok(rows_affected > 0) + } + + pub async fn get_by_id(pool: &SqlitePool, id: &str) -> Result { + let order = sqlx::query_as::<_, Order>( + r#" + SELECT * FROM orders WHERE id = ? + LIMIT 1 + "#, + ) + .bind(id) + .fetch_one(pool) + .await?; + + Ok(order) + } + + pub async fn get_all(pool: &SqlitePool) -> Result> { + let orders = sqlx::query_as::<_, Order>(r#"SELECT * FROM orders"#) + .fetch_all(pool) + .await?; + Ok(orders) + } +} diff --git a/mostro-cli/src/error.rs b/mostro-cli/src/error.rs new file mode 100644 index 00000000..fa6ebafd --- /dev/null +++ b/mostro-cli/src/error.rs @@ -0,0 +1,42 @@ +use std::fmt; + +#[derive(Debug)] +pub enum MostroError { + ParsingInvoiceError, + ParsingNumberError, + InvoiceExpiredError, + MinExpirationTimeError, + MinAmountError, +} + +impl std::error::Error for MostroError {} + +impl fmt::Display for MostroError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MostroError::ParsingInvoiceError => write!(f, "Incorrect invoice"), + MostroError::ParsingNumberError => write!(f, "Error parsing the number"), + MostroError::InvoiceExpiredError => write!(f, "Invoice has expired"), + MostroError::MinExpirationTimeError => write!(f, "Minimal expiration time on invoice"), + MostroError::MinAmountError => write!(f, "Minimal payment amount"), + } + } +} + +impl From for MostroError { + fn from(_: lightning_invoice::ParseError) -> Self { + MostroError::ParsingInvoiceError + } +} + +impl From for MostroError { + fn from(_: lightning_invoice::ParseOrSemanticError) -> Self { + MostroError::ParsingInvoiceError + } +} + +impl From for MostroError { + fn from(_: std::num::ParseIntError) -> Self { + MostroError::ParsingNumberError + } +} diff --git a/mostro-cli/src/fiat.rs b/mostro-cli/src/fiat.rs new file mode 100644 index 00000000..a7d01be3 --- /dev/null +++ b/mostro-cli/src/fiat.rs @@ -0,0 +1,1468 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +pub type FiatNames = HashMap; +pub type FiatList = Vec<(String, String)>; + +#[derive(Debug, Serialize, Deserialize)] +pub struct FiatNamesValue { + #[serde(rename = "symbol")] + symbol: String, + + #[serde(rename = "name")] + name: String, + + #[serde(rename = "symbol_native")] + symbol_native: String, + + #[serde(rename = "decimal_digits")] + decimal_digits: i64, + + #[serde(rename = "rounding")] + rounding: f64, + + #[serde(rename = "code")] + code: String, + + #[serde(rename = "emoji")] + emoji: String, + + #[serde(rename = "name_plural")] + name_plural: String, + + #[serde(rename = "price")] + price: Option, + + #[serde(rename = "locale")] + locale: Option, +} + +pub fn check_currency_ticker(currency: String) -> Option { + let upper = currency.to_uppercase(); + let mut selectedcurrency: Option = None; + let mut description = String::new(); + + let list = load_fiat_values(); + + for curr in list.iter() { + if curr.0 == upper { + selectedcurrency = Some(curr.0.to_owned()); + description = curr.1.to_owned(); + } + } + + match selectedcurrency.clone() { + Some(s) => println!("You have selected all offers of {} - {}", s, description), + None => println!("Mmmmhhh you shouldn't be arrived here...something bad!"), + } + + selectedcurrency +} + +pub fn load_fiat_values() -> FiatList { + let fiat_names = r#" + { + "AED": { + "symbol": "AED", + "name": "United Arab Emirates Dirham", + "symbol_native": "د.إ.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "AED", + "emoji": "🇦🇪", + "name_plural": "UAE dirhams", + "price": true + }, + "AFN": { + "symbol": "Af", + "name": "Afghan Afghani", + "symbol_native": "؋", + "decimal_digits": 0, + "rounding": 0, + "code": "AFN", + "emoji": "", + "name_plural": "Afghan Afghanis" + }, + "ALL": { + "symbol": "ALL", + "name": "Albanian Lek", + "symbol_native": "Lek", + "decimal_digits": 0, + "rounding": 0, + "code": "ALL", + "emoji": "", + "name_plural": "Albanian lekë" + }, + "AMD": { + "symbol": "AMD", + "name": "Armenian Dram", + "symbol_native": "դր.", + "decimal_digits": 0, + "rounding": 0, + "code": "AMD", + "emoji": "", + "name_plural": "Armenian drams" + }, + "ANG": { + "symbol": "ANG", + "name": "Netherlands Antillean Guilder", + "symbol_native": "NAƒ", + "decimal_digits": 2, + "rounding": 0, + "code": "ANG", + "emoji": "🇧🇶", + "name_plural": "ANG", + "price": true + }, + "AOA": { + "symbol": "AOA", + "name": "Angolan Kwanza", + "symbol_native": "Kz", + "decimal_digits": 2, + "rounding": 0, + "code": "AOA", + "emoji": "🇦🇴", + "name_plural": "AOA", + "price": true + }, + "ARS": { + "symbol": "AR$", + "name": "Peso argentino", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "ARS", + "emoji": "🇦🇷", + "name_plural": "Pesos", + "price": true, + "locale": "es-AR" + }, + "AUD": { + "symbol": "AU$", + "name": "Australian Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "AUD", + "emoji": "🇦🇺", + "name_plural": "Australian dollars", + "price": true, + "locale": "en-AU" + }, + "AZN": { + "symbol": "man.", + "name": "Azerbaijani Manat", + "symbol_native": "ман.", + "decimal_digits": 2, + "rounding": 0, + "code": "AZN", + "emoji": "🇦🇿", + "name_plural": "Azerbaijani manats", + "price": true + }, + "BAM": { + "symbol": "KM", + "name": "Bosnia-Herzegovina Convertible Mark", + "symbol_native": "KM", + "decimal_digits": 2, + "rounding": 0, + "code": "BAM", + "emoji": "", + "name_plural": "Bosnia-Herzegovina convertible marks" + }, + "BDT": { + "symbol": "Tk", + "name": "Bangladeshi Taka", + "symbol_native": "৳", + "decimal_digits": 2, + "rounding": 0, + "code": "BDT", + "emoji": "🇧🇩", + "name_plural": "Bangladeshi takas", + "price": true + }, + "BGN": { + "symbol": "BGN", + "name": "Bulgarian Lev", + "symbol_native": "лв.", + "decimal_digits": 2, + "rounding": 0, + "code": "BGN", + "emoji": "", + "name_plural": "Bulgarian leva" + }, + "BHD": { + "symbol": "BHD", + "name": "Bahraini Dinar", + "symbol_native": "د.ب.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "BHD", + "emoji": "🇧🇭", + "name_plural": "Bahraini dinars", + "price": true + }, + "BIF": { + "symbol": "FBu", + "name": "Burundian Franc", + "symbol_native": "FBu", + "decimal_digits": 0, + "rounding": 0, + "code": "BIF", + "emoji": "", + "name_plural": "Burundian francs" + }, + "BMD": { + "symbol": "BMD", + "name": "Bermudan Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "BMD", + "emoji": "🇧🇲", + "name_plural": "Bermudan Dollar", + "price": true + }, + "BND": { + "symbol": "BN$", + "name": "Brunei Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "BND", + "emoji": "", + "name_plural": "Brunei dollars" + }, + "BOB": { + "symbol": "Bs", + "name": "Boliviano", + "symbol_native": "Bs", + "decimal_digits": 2, + "rounding": 0, + "code": "BOB", + "emoji": "🇧🇴", + "name_plural": "Bolivianos", + "price": true, + "locale": "es-BO" + }, + "BRL": { + "symbol": "R$", + "name": "Brazilian Real", + "symbol_native": "R$", + "decimal_digits": 2, + "rounding": 0, + "code": "BRL", + "emoji": "🇧🇷", + "name_plural": "Brazilian reals", + "price": true, + "locale": "pt-BR" + }, + "BWP": { + "symbol": "BWP", + "name": "Botswanan Pula", + "symbol_native": "P", + "decimal_digits": 2, + "rounding": 0, + "code": "BWP", + "emoji": "", + "name_plural": "Botswanan pulas", + "price": true + }, + "BYN": { + "symbol": "Br", + "name": "Belarusian Ruble", + "symbol_native": "руб.", + "decimal_digits": 2, + "rounding": 0, + "code": "BYN", + "emoji": "🇧🇾", + "name_plural": "Belarusian rubles", + "price": true + }, + "BZD": { + "symbol": "BZ$", + "name": "Belize Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "BZD", + "emoji": "", + "name_plural": "Belize dollars" + }, + "CAD": { + "symbol": "CA$", + "name": "Canadian Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "CAD", + "emoji": "🇨🇦", + "name_plural": "Canadian dollars", + "price": true, + "locale": "en-CA" + }, + "CDF": { + "symbol": "CDF", + "name": "Congolese Franc", + "symbol_native": "FrCD", + "decimal_digits": 2, + "rounding": 0, + "code": "CDF", + "emoji": "", + "name_plural": "Congolese francs", + "price": true + }, + "CHF": { + "symbol": "CHF", + "name": "Swiss Franc", + "symbol_native": "CHF", + "decimal_digits": 2, + "rounding": 0.05, + "code": "CHF", + "emoji": "🇨🇭", + "name_plural": "Swiss francs", + "price": true + }, + "CLP": { + "symbol": "CL$", + "name": "Peso chileno", + "symbol_native": "$", + "decimal_digits": 0, + "rounding": 0, + "code": "CLP", + "emoji": "🇨🇱", + "name_plural": "Pesos", + "price": true, + "locale": "es-CL" + }, + "CNY": { + "symbol": "CN¥", + "name": "Chinese Yuan", + "symbol_native": "CN¥", + "decimal_digits": 2, + "rounding": 0, + "code": "CNY", + "emoji": "🇨🇳", + "name_plural": "Chinese yuan", + "price": true + }, + "COP": { + "symbol": "CO$", + "name": "Peso colombiano", + "symbol_native": "$", + "decimal_digits": 0, + "rounding": 0, + "code": "COP", + "emoji": "🇨🇴", + "name_plural": "Pesos", + "price": true, + "locale": "es-CO" + }, + "CRC": { + "symbol": "₡", + "name": "Colón", + "symbol_native": "₡", + "decimal_digits": 0, + "rounding": 0, + "code": "CRC", + "emoji": "🇨🇷", + "name_plural": "Colones", + "price": true, + "locale": "es-CR" + }, + "CUP": { + "symbol": "CU$", + "name": "Peso cubano", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "CUP", + "emoji": "🇨🇺", + "name_plural": "Pesos", + "price": true, + "locale": "es-AR" + }, + "CVE": { + "symbol": "CV$", + "name": "Cape Verdean Escudo", + "symbol_native": "CV$", + "decimal_digits": 2, + "rounding": 0, + "code": "CVE", + "emoji": "", + "name_plural": "Cape Verdean escudos" + }, + "CZK": { + "symbol": "Kč", + "name": "Czech Republic Koruna", + "symbol_native": "Kč", + "decimal_digits": 2, + "rounding": 0, + "code": "CZK", + "emoji": "🇨🇿", + "name_plural": "Czech Republic korunas", + "price": true + }, + "DJF": { + "symbol": "Fdj", + "name": "Djiboutian Franc", + "symbol_native": "Fdj", + "decimal_digits": 0, + "rounding": 0, + "code": "DJF", + "emoji": "", + "name_plural": "Djiboutian francs" + }, + "DKK": { + "symbol": "Dkr", + "name": "Danish Krone", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "DKK", + "emoji": "🇩🇰", + "name_plural": "Danish kroner", + "price": true + }, + "DOP": { + "symbol": "RD$", + "name": "Peso dominicano", + "symbol_native": "RD$", + "decimal_digits": 2, + "rounding": 0, + "code": "DOP", + "emoji": "🇩🇴", + "name_plural": "Pesos", + "price": true, + "locale": "es-DO" + }, + "DZD": { + "symbol": "DA", + "name": "Algerian Dinar", + "symbol_native": "د.ج.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "DZD", + "emoji": "🇩🇿", + "name_plural": "Algerian dinars", + "price": true + }, + "EEK": { + "symbol": "Ekr", + "name": "Estonian Kroon", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "EEK", + "emoji": "", + "name_plural": "Estonian kroons" + }, + "EGP": { + "symbol": "EGP", + "name": "Egyptian Pound", + "symbol_native": "ج.م.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "EGP", + "emoji": "🇪🇬", + "name_plural": "Egyptian pounds", + "price": true + }, + "ERN": { + "symbol": "Nfk", + "name": "Eritrean Nakfa", + "symbol_native": "Nfk", + "decimal_digits": 2, + "rounding": 0, + "code": "ERN", + "emoji": "", + "name_plural": "Eritrean nakfas" + }, + "ETB": { + "symbol": "Br", + "name": "Ethiopian Birr", + "symbol_native": "Br", + "decimal_digits": 2, + "rounding": 0, + "code": "ETB", + "emoji": "🇪🇹", + "name_plural": "Ethiopian birrs", + "price": true + }, + "EUR": { + "symbol": "€", + "name": "Euro", + "symbol_native": "€", + "decimal_digits": 2, + "rounding": 0, + "code": "EUR", + "emoji": "🇪🇺", + "name_plural": "euros", + "price": true, + "locale": "de-DE" + }, + "GBP": { + "symbol": "£", + "name": "British Pound Sterling", + "symbol_native": "£", + "decimal_digits": 2, + "rounding": 0, + "code": "GBP", + "emoji": "🇬🇧", + "name_plural": "British pounds sterling", + "price": true + }, + "GEL": { + "symbol": "GEL", + "name": "Georgian Lari", + "symbol_native": "GEL", + "decimal_digits": 2, + "rounding": 0, + "code": "GEL", + "emoji": "🇬🇪", + "name_plural": "Georgian laris", + "price": true + }, + "GHS": { + "symbol": "GH₵", + "name": "Ghanaian Cedi", + "symbol_native": "GH₵", + "decimal_digits": 2, + "rounding": 0, + "code": "GHS", + "emoji": "🇬🇭", + "name_plural": "Ghanaian cedis", + "price": true + }, + "GNF": { + "symbol": "FG", + "name": "Guinean Franc", + "symbol_native": "FG", + "decimal_digits": 0, + "rounding": 0, + "code": "GNF", + "emoji": "", + "name_plural": "Guinean francs" + }, + "GTQ": { + "symbol": "GTQ", + "name": "Quetzal", + "symbol_native": "Q", + "decimal_digits": 2, + "rounding": 0, + "code": "GTQ", + "emoji": "🇬🇹", + "name_plural": "Quetzales", + "price": true + }, + "HKD": { + "symbol": "HK$", + "name": "Hong Kong Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "HKD", + "emoji": "🇭🇰", + "name_plural": "Hong Kong dollars", + "price": true + }, + "HNL": { + "symbol": "HNL", + "name": "Lempira", + "symbol_native": "L", + "decimal_digits": 2, + "rounding": 0, + "code": "HNL", + "emoji": "🇭🇳", + "name_plural": "Lempiras", + "price": true + }, + "HRK": { + "symbol": "kn", + "name": "Croatian Kuna", + "symbol_native": "kn", + "decimal_digits": 2, + "rounding": 0, + "code": "HRK", + "emoji": "", + "name_plural": "Croatian kunas" + }, + "HUF": { + "symbol": "Ft", + "name": "Hungarian Forint", + "symbol_native": "Ft", + "decimal_digits": 0, + "rounding": 0, + "code": "HUF", + "emoji": "🇭🇺", + "name_plural": "Hungarian forints", + "price": true + }, + "IDR": { + "symbol": "Rp", + "name": "Indonesian Rupiah", + "symbol_native": "Rp", + "decimal_digits": 0, + "rounding": 0, + "code": "IDR", + "emoji": "🇮🇩", + "name_plural": "Indonesian rupiahs", + "price": true + }, + "ILS": { + "symbol": "₪", + "name": "Israeli New Sheqel", + "symbol_native": "₪", + "decimal_digits": 2, + "rounding": 0, + "code": "ILS", + "emoji": "🇮🇱", + "name_plural": "Israeli new sheqels", + "price": true + }, + "INR": { + "symbol": "Rs", + "name": "Indian Rupee", + "symbol_native": "টকা", + "decimal_digits": 2, + "rounding": 0, + "code": "INR", + "emoji": "🇮🇳", + "name_plural": "Indian rupees", + "price": true + }, + "IQD": { + "symbol": "IQD", + "name": "Iraqi Dinar", + "symbol_native": "د.ع.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "IQD", + "emoji": "", + "name_plural": "Iraqi dinars" + }, + "IRR": { + "symbol": "IRR", + "name": "Iranian Rial", + "symbol_native": "﷼", + "decimal_digits": 0, + "rounding": 0, + "code": "IRR", + "emoji": "", + "name_plural": "Iranian rials" + }, + "ISK": { + "symbol": "Ikr", + "name": "Icelandic Króna", + "symbol_native": "kr", + "decimal_digits": 0, + "rounding": 0, + "code": "ISK", + "emoji": "", + "name_plural": "Icelandic krónur" + }, + "JMD": { + "symbol": "J$", + "name": "Jamaican Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "JMD", + "emoji": "🇯🇲", + "name_plural": "Jamaican dollars", + "price": true + }, + "JOD": { + "symbol": "JD", + "name": "Jordanian Dinar", + "symbol_native": "د.أ.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "JOD", + "emoji": "🇯🇴", + "name_plural": "Jordanian dinars", + "price": true + }, + "JPY": { + "symbol": "¥", + "name": "Japanese Yen", + "symbol_native": "¥", + "decimal_digits": 0, + "rounding": 0, + "code": "JPY", + "emoji": "🇯🇵", + "name_plural": "Japanese yen", + "price": true + }, + "KES": { + "symbol": "Ksh", + "name": "Kenyan Shilling", + "symbol_native": "Ksh", + "decimal_digits": 2, + "rounding": 0, + "code": "KES", + "emoji": "🇰🇪", + "name_plural": "Kenyan shillings", + "price": true + }, + "KGS": { + "symbol": "KGS", + "name": "Kyrgystani Som", + "symbol_native": "KGS", + "decimal_digits": 2, + "rounding": 0, + "code": "KGS", + "emoji": "🇰🇬", + "name_plural": "Kyrgystani Som", + "price": true + }, + "KHR": { + "symbol": "KHR", + "name": "Cambodian Riel", + "symbol_native": "៛", + "decimal_digits": 2, + "rounding": 0, + "code": "KHR", + "emoji": "", + "name_plural": "Cambodian riels" + }, + "KMF": { + "symbol": "CF", + "name": "Comorian Franc", + "symbol_native": "FC", + "decimal_digits": 0, + "rounding": 0, + "code": "KMF", + "emoji": "", + "name_plural": "Comorian francs" + }, + "KRW": { + "symbol": "₩", + "name": "South Korean Won", + "symbol_native": "₩", + "decimal_digits": 0, + "rounding": 0, + "code": "KRW", + "emoji": "🇰🇷", + "name_plural": "South Korean won", + "price": true + }, + "KWD": { + "symbol": "KD", + "name": "Kuwaiti Dinar", + "symbol_native": "د.ك.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "KWD", + "emoji": "", + "name_plural": "Kuwaiti dinars" + }, + "KZT": { + "symbol": "KZT", + "name": "Kazakhstani Tenge", + "symbol_native": "тңг.", + "decimal_digits": 2, + "rounding": 0, + "code": "KZT", + "emoji": "🇰🇿", + "name_plural": "Kazakhstani tenges", + "price": true + }, + "LBP": { + "symbol": "L.L.", + "name": "Lebanese Pound", + "symbol_native": "ل.ل.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "LBP", + "emoji": "🇱🇧", + "name_plural": "Lebanese pounds", + "price": true + }, + "LKR": { + "symbol": "SLRs", + "name": "Sri Lankan Rupee", + "symbol_native": "SL Re", + "decimal_digits": 2, + "rounding": 0, + "code": "LKR", + "emoji": "🇱🇰", + "name_plural": "Sri Lankan rupees", + "price": true + }, + "LTL": { + "symbol": "Lt", + "name": "Lithuanian Litas", + "symbol_native": "Lt", + "decimal_digits": 2, + "rounding": 0, + "code": "LTL", + "emoji": "", + "name_plural": "Lithuanian litai" + }, + "LVL": { + "symbol": "Ls", + "name": "Latvian Lats", + "symbol_native": "Ls", + "decimal_digits": 2, + "rounding": 0, + "code": "LVL", + "emoji": "", + "name_plural": "Latvian lati" + }, + "LYD": { + "symbol": "LD", + "name": "Libyan Dinar", + "symbol_native": "د.ل.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "LYD", + "emoji": "", + "name_plural": "Libyan dinars" + }, + "MAD": { + "symbol": "MAD", + "name": "Moroccan Dirham", + "symbol_native": "د.م.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "MAD", + "emoji": "🇲🇦", + "name_plural": "Moroccan dirhams", + "price": true + }, + "MDL": { + "symbol": "MDL", + "name": "Moldovan Leu", + "symbol_native": "MDL", + "decimal_digits": 2, + "rounding": 0, + "code": "MDL", + "emoji": "", + "name_plural": "Moldovan lei" + }, + "MGA": { + "symbol": "MGA", + "name": "Malagasy Ariary", + "symbol_native": "MGA", + "decimal_digits": 0, + "rounding": 0, + "code": "MGA", + "emoji": "", + "name_plural": "Malagasy Ariaries" + }, + "MKD": { + "symbol": "MKD", + "name": "Macedonian Denar", + "symbol_native": "MKD", + "decimal_digits": 2, + "rounding": 0, + "code": "MKD", + "emoji": "", + "name_plural": "Macedonian denari" + }, + "MLC": { + "symbol": "MLC", + "name": "Moneda Libremente Convertible", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "MLC", + "emoji": "🇨🇺", + "name_plural": "MLC", + "price": true, + "locale": "es-AR" + }, + "MMK": { + "symbol": "MMK", + "name": "Myanma Kyat", + "symbol_native": "K", + "decimal_digits": 0, + "rounding": 0, + "code": "MMK", + "emoji": "", + "name_plural": "Myanma kyats" + }, + "MOP": { + "symbol": "MOP$", + "name": "Macanese Pataca", + "symbol_native": "MOP$", + "decimal_digits": 2, + "rounding": 0, + "code": "MOP", + "emoji": "", + "name_plural": "Macanese patacas" + }, + "MUR": { + "symbol": "MURs", + "name": "Mauritian Rupee", + "symbol_native": "MURs", + "decimal_digits": 0, + "rounding": 0, + "code": "MUR", + "emoji": "", + "name_plural": "Mauritian rupees" + }, + "MXN": { + "symbol": "MX$", + "name": "Peso mexicano", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "MXN", + "emoji": "🇲🇽", + "name_plural": "Pesos", + "price": true, + "locale": "es-MX" + }, + "MYR": { + "symbol": "RM", + "name": "Malaysian Ringgit", + "symbol_native": "RM", + "decimal_digits": 2, + "rounding": 0, + "code": "MYR", + "emoji": "🇲🇾", + "name_plural": "Malaysian ringgits", + "price": true + }, + "MZN": { + "symbol": "MTn", + "name": "Mozambican Metical", + "symbol_native": "MTn", + "decimal_digits": 2, + "rounding": 0, + "code": "MZN", + "emoji": "", + "name_plural": "Mozambican meticals" + }, + "NAD": { + "symbol": "N$", + "name": "Namibian Dollar", + "symbol_native": "N$", + "decimal_digits": 2, + "rounding": 0, + "code": "NAD", + "emoji": "🇳🇦", + "name_plural": "Namibian dollars", + "price": true + }, + "NGN": { + "symbol": "₦", + "name": "Nigerian Naira", + "symbol_native": "₦", + "decimal_digits": 2, + "rounding": 0, + "code": "NGN", + "emoji": "🇳🇬", + "name_plural": "Nigerian nairas", + "price": true + }, + "NIO": { + "symbol": "C$", + "name": "Nicaraguan Córdoba", + "symbol_native": "C$", + "decimal_digits": 2, + "rounding": 0, + "code": "NIO", + "emoji": "🇳🇮", + "name_plural": "Nicaraguan córdobas", + "price": true + }, + "NOK": { + "symbol": "Nkr", + "name": "Norwegian Krone", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "NOK", + "emoji": "🇳🇴", + "name_plural": "Norwegian kroner", + "price": true + }, + "NPR": { + "symbol": "NPRs", + "name": "Nepalese Rupee", + "symbol_native": "नेरू", + "decimal_digits": 2, + "rounding": 0, + "code": "NPR", + "emoji": "🇳🇵", + "name_plural": "Nepalese rupees", + "price": true + }, + "NZD": { + "symbol": "NZ$", + "name": "New Zealand Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "NZD", + "emoji": "🇳🇿", + "name_plural": "New Zealand dollars", + "price": true + }, + "OMR": { + "symbol": "OMR", + "name": "Omani Rial", + "symbol_native": "ر.ع.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "OMR", + "emoji": "", + "name_plural": "Omani rials" + }, + "PAB": { + "symbol": "B/.", + "name": "Panamanian Balboa", + "symbol_native": "B/.", + "decimal_digits": 2, + "rounding": 0, + "code": "PAB", + "emoji": "🇵🇦", + "name_plural": "Balboas", + "price": true + }, + "PEN": { + "symbol": "S/.", + "name": "Peruvian Nuevo Sol", + "symbol_native": "S/.", + "decimal_digits": 2, + "rounding": 0, + "code": "PEN", + "emoji": "🇵🇪", + "name_plural": "Nuevos soles peruanos", + "price": true, + "locale": "es-PE" + }, + "PHP": { + "symbol": "₱", + "name": "Philippine Peso", + "symbol_native": "₱", + "decimal_digits": 2, + "rounding": 0, + "code": "PHP", + "emoji": "🇵🇭", + "name_plural": "Pesos", + "price": true + }, + "PKR": { + "symbol": "PKRs", + "name": "Pakistani Rupee", + "symbol_native": "₨", + "decimal_digits": 0, + "rounding": 0, + "code": "PKR", + "emoji": "🇵🇰", + "name_plural": "Pakistani rupees", + "price": true + }, + "PLN": { + "symbol": "zł", + "name": "Polish Zloty", + "symbol_native": "zł", + "decimal_digits": 2, + "rounding": 0, + "code": "PLN", + "emoji": "🇵🇱", + "name_plural": "Polish zlotys", + "price": true + }, + "PYG": { + "symbol": "₲", + "name": "Paraguayan Guarani", + "symbol_native": "₲", + "decimal_digits": 0, + "rounding": 0, + "code": "PYG", + "emoji": "🇵🇾", + "name_plural": "Guaranis", + "price": true + }, + "QAR": { + "symbol": "QR", + "name": "Qatari Rial", + "symbol_native": "ر.ق.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "QAR", + "emoji": "🇶🇦", + "name_plural": "Qatari rials", + "price": true + }, + "RON": { + "symbol": "RON", + "name": "Romanian Leu", + "symbol_native": "RON", + "decimal_digits": 2, + "rounding": 0, + "code": "RON", + "emoji": "🇷🇴", + "name_plural": "Romanian lei", + "price": true + }, + "RSD": { + "symbol": "din.", + "name": "Serbian Dinar", + "symbol_native": "дин.", + "decimal_digits": 0, + "rounding": 0, + "code": "RSD", + "emoji": "", + "name_plural": "Serbian dinars", + "price": true + }, + "RUB": { + "symbol": "RUB", + "name": "руб", + "symbol_native": "₽.", + "decimal_digits": 2, + "rounding": 0, + "code": "RUB", + "emoji": "🇷🇺", + "name_plural": "руб", + "price": true + }, + "RWF": { + "symbol": "RWF", + "name": "Rwandan Franc", + "symbol_native": "FR", + "decimal_digits": 0, + "rounding": 0, + "code": "RWF", + "emoji": "", + "name_plural": "Rwandan francs" + }, + "SAR": { + "symbol": "SR", + "name": "Saudi Riyal", + "symbol_native": "ر.س.‏", + "decimal_digits": 2, + "rounding": 0, + "code": "SAR", + "emoji": "🇸🇦", + "name_plural": "Saudi riyals", + "price": true + }, + "SDG": { + "symbol": "SDG", + "name": "Sudanese Pound", + "symbol_native": "SDG", + "decimal_digits": 2, + "rounding": 0, + "code": "SDG", + "emoji": "", + "name_plural": "Sudanese pounds" + }, + "SEK": { + "symbol": "Skr", + "name": "Swedish Krona", + "symbol_native": "kr", + "decimal_digits": 2, + "rounding": 0, + "code": "SEK", + "emoji": "🇸🇪", + "name_plural": "Swedish kronor", + "price": true + }, + "SGD": { + "symbol": "S$", + "name": "Singapore Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "SGD", + "emoji": "🇸🇬", + "name_plural": "Singapore dollars", + "price": true + }, + "SOS": { + "symbol": "Ssh", + "name": "Somali Shilling", + "symbol_native": "Ssh", + "decimal_digits": 0, + "rounding": 0, + "code": "SOS", + "emoji": "", + "name_plural": "Somali shillings" + }, + "SYP": { + "symbol": "SY£", + "name": "Syrian Pound", + "symbol_native": "ل.س.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "SYP", + "emoji": "", + "name_plural": "Syrian pounds" + }, + "THB": { + "symbol": "฿", + "name": "Thai Baht", + "symbol_native": "฿", + "decimal_digits": 2, + "rounding": 0, + "code": "THB", + "emoji": "🇹🇭", + "name_plural": "Thai baht", + "price": true + }, + "TND": { + "symbol": "DT", + "name": "Tunisian Dinar", + "symbol_native": "د.ت.‏", + "decimal_digits": 3, + "rounding": 0, + "code": "TND", + "emoji": "🇹🇳", + "name_plural": "Tunisian dinars", + "price": true + }, + "TOP": { + "symbol": "T$", + "name": "Tongan Paʻanga", + "symbol_native": "T$", + "decimal_digits": 2, + "rounding": 0, + "code": "TOP", + "emoji": "", + "name_plural": "Tongan paʻanga" + }, + "TRY": { + "symbol": "TL", + "name": "Turkish Lira", + "symbol_native": "TL", + "decimal_digits": 2, + "rounding": 0, + "code": "TRY", + "emoji": "🇹🇷", + "name_plural": "Turkish Lira", + "price": true + }, + "TTD": { + "symbol": "TT$", + "name": "Trinidad and Tobago Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "TTD", + "emoji": "🇹🇹", + "name_plural": "Trinidad and Tobago dollars", + "price": true + }, + "TWD": { + "symbol": "NT$", + "name": "New Taiwan Dollar", + "symbol_native": "NT$", + "decimal_digits": 2, + "rounding": 0, + "code": "TWD", + "emoji": "🇹🇼", + "name_plural": "New Taiwan dollars", + "price": true + }, + "TZS": { + "symbol": "TSh", + "name": "Tanzanian Shilling", + "symbol_native": "TSh", + "decimal_digits": 0, + "rounding": 0, + "code": "TZS", + "emoji": "🇹🇿", + "name_plural": "Tanzanian shillings", + "price": true + }, + "UAH": { + "symbol": "₴", + "name": "Ukrainian Hryvnia", + "symbol_native": "₴", + "decimal_digits": 2, + "rounding": 0, + "code": "UAH", + "emoji": "🇺🇦", + "name_plural": "Ukrainian hryvnias", + "price": true + }, + "UGX": { + "symbol": "USh", + "name": "Ugandan Shilling", + "symbol_native": "USh", + "decimal_digits": 0, + "rounding": 0, + "code": "UGX", + "emoji": "🇺🇬", + "name_plural": "Ugandan shillings", + "price": true + }, + "USD": { + "symbol": "$", + "name": "US Dollar", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "USD", + "emoji": "🇺🇸", + "name_plural": "US dollars", + "price": true, + "locale": "en-US" + }, + "USDSV": { + "symbol": "$", + "name": "USD en El Salvador", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "USDSV", + "emoji": "🇺🇸🇸🇻", + "name_plural": "USD en El Salvador", + "price": true, + "locale": "es-SV" + }, + "USDVE": { + "symbol": "$", + "name": "USD en Bs", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "USDVE", + "emoji": "🇺🇸🇻🇪", + "name_plural": "USD en Bs", + "price": true, + "locale": "es-VE" + }, + "USDUY": { + "symbol": "$", + "name": "USD en Uruguay", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "USDUY", + "emoji": "🇺🇸🇺🇾", + "name_plural": "USD en Uruguay", + "price": true, + "locale": "es-UY" + }, + "UYU": { + "symbol": "$U", + "name": "Peso uruguayo", + "symbol_native": "$", + "decimal_digits": 2, + "rounding": 0, + "code": "UYU", + "emoji": "🇺🇾", + "name_plural": "Pesos", + "price": true, + "locale": "es-UY" + }, + "UZS": { + "symbol": "UZS", + "name": "Uzbekistan Som", + "symbol_native": "UZS", + "decimal_digits": 0, + "rounding": 0, + "code": "UZS", + "emoji": "🇺🇿", + "name_plural": "Uzbekistan som", + "price": true + }, + "VES": { + "symbol": "Bs.", + "name": "Bolívar", + "symbol_native": "Bs.", + "decimal_digits": 2, + "rounding": 0, + "code": "VES", + "emoji": "🇻🇪", + "name_plural": "Bolívares", + "price": true, + "locale": "es-VE" + }, + "VND": { + "symbol": "₫", + "name": "Vietnamese Dong", + "symbol_native": "₫", + "decimal_digits": 0, + "rounding": 0, + "code": "VND", + "emoji": "🇻🇳", + "name_plural": "Vietnamese dong", + "price": true + }, + "XAF": { + "symbol": "FCFA", + "name": "CFA Franc BEAC", + "symbol_native": "FCFA", + "decimal_digits": 0, + "rounding": 0, + "code": "XAF", + "emoji": "🏳️", + "name_plural": "CFA francs BEAC", + "price": true + }, + "XOF": { + "symbol": "CFA", + "name": "CFA Franc BCEAO", + "symbol_native": "CFA", + "decimal_digits": 0, + "rounding": 0, + "code": "XOF", + "emoji": "🏳️", + "name_plural": "CFA francs BCEAO", + "price": true + }, + "YER": { + "symbol": "YR", + "name": "Yemeni Rial", + "symbol_native": "ر.ي.‏", + "decimal_digits": 0, + "rounding": 0, + "code": "YER", + "emoji": "", + "name_plural": "Yemeni rials" + }, + "ZAR": { + "symbol": "R", + "name": "South African Rand", + "symbol_native": "R", + "decimal_digits": 2, + "rounding": 0, + "code": "ZAR", + "emoji": "🇿🇦", + "name_plural": "South African rand", + "price": true + }, + "ZMK": { + "symbol": "ZK", + "name": "Zambian Kwacha", + "symbol_native": "ZK", + "decimal_digits": 0, + "rounding": 0, + "code": "ZMK", + "emoji": "", + "name_plural": "Zambian kwachas" + }, + "ZWL": { + "symbol": "ZWL$", + "name": "Zimbabwean Dollar", + "symbol_native": "ZWL$", + "decimal_digits": 0, + "rounding": 0, + "code": "ZWL", + "emoji": "🇿🇼", + "name_plural": "Zimbabwean Dollar" + } + }"#; + + let fiat_json: FiatNames = serde_json::from_str(fiat_names).unwrap(); + + let mut fiatlist = FiatList::new(); + + for elem in fiat_json.iter() { + fiatlist.push((elem.0.to_string(), elem.1.name.clone())); + } + + //Return list + fiatlist.sort_by(|a, b| a.0.cmp(&b.0)); + + fiatlist +} diff --git a/mostro-cli/src/lib.rs b/mostro-cli/src/lib.rs new file mode 100644 index 00000000..ce395792 --- /dev/null +++ b/mostro-cli/src/lib.rs @@ -0,0 +1,7 @@ +pub mod cli; +pub mod db; +pub mod error; +pub mod lightning; +pub mod nip33; +pub mod pretty_table; +pub mod util; diff --git a/mostro-cli/src/lightning/mod.rs b/mostro-cli/src/lightning/mod.rs new file mode 100644 index 00000000..33c57dff --- /dev/null +++ b/mostro-cli/src/lightning/mod.rs @@ -0,0 +1,13 @@ +use crate::error::MostroError; +use lightning_invoice::Invoice; +use std::str::FromStr; + +/// Verify if an invoice is valid +pub fn is_valid_invoice(payment_request: &str) -> Result { + let invoice = Invoice::from_str(payment_request)?; + if invoice.is_expired() { + return Err(MostroError::InvoiceExpiredError); + } + + Ok(invoice) +} diff --git a/mostro-cli/src/main.rs b/mostro-cli/src/main.rs new file mode 100644 index 00000000..d6f20d9c --- /dev/null +++ b/mostro-cli/src/main.rs @@ -0,0 +1,16 @@ +use anyhow::Result; +use dotenvy::dotenv; +use mostro_client::cli::run; +use std::process; + +#[tokio::main] +async fn main() -> Result<()> { + dotenv().ok(); + + if let Err(e) = run().await { + eprintln!("{e}"); + process::exit(1); + } + + process::exit(0); +} diff --git a/mostro-cli/src/nip33.rs b/mostro-cli/src/nip33.rs new file mode 100644 index 00000000..9209bb9a --- /dev/null +++ b/mostro-cli/src/nip33.rs @@ -0,0 +1,89 @@ +use anyhow::{Ok, Result}; +use mostro_core::dispute::{Dispute, Status as DisputeStatus}; +use mostro_core::order::{Kind as OrderKind, SmallOrder, Status}; +use nostr_sdk::prelude::*; +use std::str::FromStr; +use uuid::Uuid; + +pub fn order_from_tags(tags: Tags) -> Result { + let mut order = SmallOrder::default(); + for tag in tags { + let t = tag.to_vec(); + let v = t.get(1).unwrap().as_str(); + match t.first().unwrap().as_str() { + "d" => { + let id = v.parse::(); + let id = match id { + core::result::Result::Ok(id) => Some(id), + Err(_) => None, + }; + order.id = id; + } + "k" => { + order.kind = Some(OrderKind::from_str(v).unwrap()); + } + "f" => { + order.fiat_code = v.to_string(); + } + "s" => { + order.status = Some(Status::from_str(v).unwrap_or(Status::Dispute)); + } + "amt" => { + order.amount = v.parse::().unwrap(); + } + "fa" => { + if v.contains('.') { + continue; + } + let max = t.get(2); + if max.is_some() { + order.min_amount = v.parse::().ok(); + order.max_amount = max.unwrap().parse::().ok(); + } else { + let fa = v.parse::(); + order.fiat_amount = fa.unwrap_or(0); + } + } + "pm" => { + order.payment_method = v.to_string(); + } + "premium" => { + order.premium = v.parse::().unwrap(); + } + _ => {} + } + } + + Ok(order) +} + +pub fn dispute_from_tags(tags: Tags) -> Result { + let mut dispute = Dispute::default(); + for tag in tags { + let t = tag.to_vec(); + let v = t.get(1).unwrap().as_str(); + match t.first().unwrap().as_str() { + "d" => { + let id = t.get(1).unwrap().as_str().parse::(); + let id = match id { + core::result::Result::Ok(id) => id, + Err(_) => return Err(anyhow::anyhow!("Invalid dispute id")), + }; + dispute.id = id; + } + + "s" => { + let status = match DisputeStatus::from_str(v) { + core::result::Result::Ok(status) => status, + Err(_) => return Err(anyhow::anyhow!("Invalid dispute status")), + }; + + dispute.status = status.to_string(); + } + + _ => {} + } + } + + Ok(dispute) +} diff --git a/mostro-cli/src/pretty_table.rs b/mostro-cli/src/pretty_table.rs new file mode 100644 index 00000000..9facff06 --- /dev/null +++ b/mostro-cli/src/pretty_table.rs @@ -0,0 +1,250 @@ +use anyhow::Result; +use chrono::DateTime; +use comfy_table::presets::UTF8_FULL; +use comfy_table::*; +use mostro_core::dispute::Dispute; +use mostro_core::message::Payload; +use mostro_core::order::{Kind, SmallOrder}; + +pub fn print_order_preview(ord: Payload) -> Result { + let single_order = match ord { + Payload::Order(o) => o, + _ => return Err("Error".to_string()), + }; + + let mut table = Table::new(); + + table + .load_preset(UTF8_FULL) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_width(160) + .set_header(vec![ + Cell::new("Buy/Sell") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Sats Amount") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Fiat Code") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Fiat Amount") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Payment method") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Premium %") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + ]); + + //Table rows + let r = Row::from(vec![ + if let Some(k) = single_order.kind { + match k { + Kind::Buy => Cell::new(k.to_string()) + .fg(Color::Green) + .set_alignment(CellAlignment::Center), + Kind::Sell => Cell::new(k.to_string()) + .fg(Color::Red) + .set_alignment(CellAlignment::Center), + } + } else { + Cell::new("BUY/SELL").set_alignment(CellAlignment::Center) + }, + if single_order.amount == 0 { + Cell::new("market price").set_alignment(CellAlignment::Center) + } else { + Cell::new(single_order.amount).set_alignment(CellAlignment::Center) + }, + Cell::new(single_order.fiat_code.to_string()).set_alignment(CellAlignment::Center), + // No range order print row + if single_order.min_amount.is_none() && single_order.max_amount.is_none() { + Cell::new(single_order.fiat_amount.to_string()).set_alignment(CellAlignment::Center) + } else { + let range_str = format!( + "{}-{}", + single_order.min_amount.unwrap(), + single_order.max_amount.unwrap() + ); + Cell::new(range_str).set_alignment(CellAlignment::Center) + }, + Cell::new(single_order.payment_method.to_string()).set_alignment(CellAlignment::Center), + Cell::new(single_order.premium.to_string()).set_alignment(CellAlignment::Center), + ]); + + table.add_row(r); + + Ok(table.to_string()) +} + +pub fn print_orders_table(orders_table: Vec) -> Result { + let mut table = Table::new(); + + //Table rows + let mut rows: Vec = Vec::new(); + + if orders_table.is_empty() { + table + .load_preset(UTF8_FULL) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_width(160) + .set_header(vec![Cell::new("Sorry...") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center)]); + + // Single row for error + let mut r = Row::new(); + + r.add_cell( + Cell::new("No offers found with requested parameters...") + .fg(Color::Red) + .set_alignment(CellAlignment::Center), + ); + + //Push single error row + rows.push(r); + } else { + table + .load_preset(UTF8_FULL) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_width(160) + .set_header(vec![ + Cell::new("Buy/Sell") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Order Id") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Status") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Amount") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Fiat Code") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Fiat Amount") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Payment method") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Created") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + ]); + + //Iterate to create table of orders + for single_order in orders_table.into_iter() { + let date = DateTime::from_timestamp(single_order.created_at.unwrap_or(0), 0); + + let r = Row::from(vec![ + if let Some(k) = single_order.kind { + match k { + Kind::Buy => Cell::new(k.to_string()) + .fg(Color::Green) + .set_alignment(CellAlignment::Center), + Kind::Sell => Cell::new(k.to_string()) + .fg(Color::Red) + .set_alignment(CellAlignment::Center), + } + } else { + Cell::new("BUY/SELL").set_alignment(CellAlignment::Center) + }, + Cell::new(single_order.id.unwrap()).set_alignment(CellAlignment::Center), + Cell::new(single_order.status.unwrap().to_string()) + .set_alignment(CellAlignment::Center), + if single_order.amount == 0 { + Cell::new("market price").set_alignment(CellAlignment::Center) + } else { + Cell::new(single_order.amount.to_string()).set_alignment(CellAlignment::Center) + }, + Cell::new(single_order.fiat_code.to_string()).set_alignment(CellAlignment::Center), + // No range order print row + if single_order.min_amount.is_none() && single_order.max_amount.is_none() { + Cell::new(single_order.fiat_amount.to_string()) + .set_alignment(CellAlignment::Center) + } else { + let range_str = format!( + "{}-{}", + single_order.min_amount.unwrap(), + single_order.max_amount.unwrap() + ); + Cell::new(range_str).set_alignment(CellAlignment::Center) + }, + Cell::new(single_order.payment_method.to_string()) + .set_alignment(CellAlignment::Center), + Cell::new(date.unwrap()), + ]); + rows.push(r); + } + } + + table.add_rows(rows); + + Ok(table.to_string()) +} + +pub fn print_disputes_table(disputes_table: Vec) -> Result { + let mut table = Table::new(); + + //Table rows + let mut rows: Vec = Vec::new(); + + if disputes_table.is_empty() { + table + .load_preset(UTF8_FULL) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_width(160) + .set_header(vec![Cell::new("Sorry...") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center)]); + + // Single row for error + let mut r = Row::new(); + + r.add_cell( + Cell::new("No disputes found with requested parameters...") + .fg(Color::Red) + .set_alignment(CellAlignment::Center), + ); + + //Push single error row + rows.push(r); + } else { + table + .load_preset(UTF8_FULL) + .set_content_arrangement(ContentArrangement::Dynamic) + .set_width(160) + .set_header(vec![ + Cell::new("Dispute Id") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Status") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + Cell::new("Created") + .add_attribute(Attribute::Bold) + .set_alignment(CellAlignment::Center), + ]); + + //Iterate to create table of orders + for single_dispute in disputes_table.into_iter() { + let date = DateTime::from_timestamp(single_dispute.created_at, 0); + + let r = Row::from(vec![ + Cell::new(single_dispute.id).set_alignment(CellAlignment::Center), + Cell::new(single_dispute.status.to_string()).set_alignment(CellAlignment::Center), + Cell::new(date.unwrap()), + ]); + rows.push(r); + } + } + + table.add_rows(rows); + + Ok(table.to_string()) +} diff --git a/mostro-cli/src/util.rs b/mostro-cli/src/util.rs new file mode 100644 index 00000000..f8111770 --- /dev/null +++ b/mostro-cli/src/util.rs @@ -0,0 +1,406 @@ +use crate::nip33::{dispute_from_tags, order_from_tags}; + +use anyhow::{Error, Result}; +use base64::engine::general_purpose; +use base64::Engine; +use dotenvy::var; +use log::{error, info}; +use mostro_core::dispute::Dispute; +use mostro_core::message::Message; +use mostro_core::order::Kind as MostroKind; +use mostro_core::order::{SmallOrder, Status}; +use mostro_core::NOSTR_REPLACEABLE_EVENT_KIND; +use nip44::v2::{decrypt_to_bytes, encrypt_to_bytes, ConversationKey}; +use nostr_sdk::prelude::*; +use std::thread::sleep; +use std::time::Duration; +use std::{fs, path::Path}; + +pub async fn send_dm( + client: &Client, + identity_keys: Option<&Keys>, + trade_keys: &Keys, + receiver_pubkey: &PublicKey, + payload: String, + expiration: Option, + to_user: bool, +) -> Result<()> { + let pow: u8 = var("POW").unwrap_or('0'.to_string()).parse().unwrap(); + let event = if to_user { + // Derive conversation key + let ck = ConversationKey::derive(trade_keys.secret_key(), receiver_pubkey); + // Encrypt payload + let encrypted_content = encrypt_to_bytes(&ck, payload.as_bytes())?; + // Encode with base64 + let b64decoded_content = general_purpose::STANDARD.encode(encrypted_content); + // Compose builder + EventBuilder::new(Kind::PrivateDirectMessage, b64decoded_content) + .pow(pow) + .tag(Tag::public_key(*receiver_pubkey)) + .sign_with_keys(trade_keys)? + } else { + let identity_keys = identity_keys + .ok_or_else(|| Error::msg("identity_keys required when to_user is false"))?; + + let message = Message::from_json(&payload).unwrap(); + // We sign the message + let sig = message.get_inner_message_kind().sign(trade_keys); + // We compose the content + let content = (message, sig); + let content = serde_json::to_string(&content).unwrap(); + // We create the rumor + let rumor = EventBuilder::text_note(content) + .pow(pow) + .build(trade_keys.public_key()); + let mut tags: Vec = Vec::with_capacity(1 + usize::from(expiration.is_some())); + tags.push(Tag::public_key(*receiver_pubkey)); + + if let Some(timestamp) = expiration { + tags.push(Tag::expiration(timestamp)); + } + let tags = Tags::new(tags); + + EventBuilder::gift_wrap(identity_keys, receiver_pubkey, rumor, tags).await? + }; + + info!("Sending event: {event:#?}"); + client.send_event(event).await?; + + Ok(()) +} + +pub async fn connect_nostr() -> Result { + let my_keys = Keys::generate(); + + let relays = var("RELAYS").expect("RELAYS is not set"); + let relays = relays.split(',').collect::>(); + // Create new client + let client = Client::new(my_keys); + // Add relays + for r in relays.into_iter() { + client.add_relay(r).await?; + } + // Connect to relays and keep connection alive + client.connect().await; + + Ok(client) +} + +pub async fn send_message_sync( + client: &Client, + identity_keys: Option<&Keys>, + trade_keys: &Keys, + receiver_pubkey: PublicKey, + message: Message, + wait_for_dm: bool, + to_user: bool, +) -> Result> { + let message_json = message.as_json()?; + // Send dm to receiver pubkey + println!( + "SENDING DM with trade keys: {:?}", + trade_keys.public_key().to_hex() + ); + send_dm( + client, + identity_keys, + trade_keys, + &receiver_pubkey, + message_json, + None, + to_user, + ) + .await?; + // FIXME: This is a hack to wait for the DM to be sent + sleep(Duration::from_secs(2)); + + let dm: Vec<(Message, u64)> = if wait_for_dm { + get_direct_messages(client, trade_keys, 15, to_user).await + } else { + Vec::new() + }; + + Ok(dm) +} + +pub async fn get_direct_messages( + client: &Client, + my_key: &Keys, + since: i64, + from_user: bool, +) -> Vec<(Message, u64)> { + // We use a fake timestamp to thwart time-analysis attacks + let fake_since = 2880; + let fake_since_time = chrono::Utc::now() + .checked_sub_signed(chrono::Duration::minutes(fake_since)) + .unwrap() + .timestamp() as u64; + + let fake_timestamp = Timestamp::from(fake_since_time); + let filters = if from_user { + let since_time = chrono::Utc::now() + .checked_sub_signed(chrono::Duration::minutes(since)) + .unwrap() + .timestamp() as u64; + let timestamp = Timestamp::from(since_time); + Filter::new() + .kind(Kind::PrivateDirectMessage) + .pubkey(my_key.public_key()) + .since(timestamp) + } else { + Filter::new() + .kind(Kind::GiftWrap) + .pubkey(my_key.public_key()) + .since(fake_timestamp) + }; + + info!("Request events with event kind : {:?} ", filters.kinds); + + let mut direct_messages: Vec<(Message, u64)> = Vec::new(); + + if let Ok(mostro_req) = client + .fetch_events(vec![filters], Duration::from_secs(15)) + .await + { + // Buffer vector for direct messages + // Vector for single order id check - maybe multiple relay could send the same order id? Check unique one... + let mut id_list = Vec::::new(); + + for dm in mostro_req.iter() { + if !id_list.contains(&dm.id) { + id_list.push(dm.id); + let created_at: Timestamp; + let message: Message; + if from_user { + let ck = ConversationKey::derive(my_key.secret_key(), &dm.pubkey); + let b64decoded_content = + match general_purpose::STANDARD.decode(dm.content.as_bytes()) { + Ok(b64decoded_content) => b64decoded_content, + Err(_) => { + continue; + } + }; + // Decrypt + let unencrypted_content = decrypt_to_bytes(&ck, &b64decoded_content).unwrap(); + let message_str = + String::from_utf8(unencrypted_content).expect("Found invalid UTF-8"); + message = Message::from_json(&message_str).unwrap(); + created_at = dm.created_at; + } else { + let unwrapped_gift = match nip59::extract_rumor(my_key, dm).await { + Ok(u) => u, + Err(_) => { + println!("Error unwrapping gift"); + continue; + } + }; + let (rumor_message, sig): (Message, nostr_sdk::secp256k1::schnorr::Signature) = + serde_json::from_str(&unwrapped_gift.rumor.content).unwrap(); + if !rumor_message + .get_inner_message_kind() + .verify_signature(unwrapped_gift.rumor.pubkey, sig) + { + println!("Signature verification failed"); + continue; + } + message = rumor_message; + created_at = unwrapped_gift.rumor.created_at; + } + // Here we discard messages older than the real since parameter + let since_time = chrono::Utc::now() + .checked_sub_signed(chrono::Duration::minutes(30)) + .unwrap() + .timestamp() as u64; + if created_at.as_u64() < since_time { + println!("Discarding message older than since parameter"); + continue; + } + direct_messages.push((message, created_at.as_u64())); + } + } + // Return element sorted by second tuple element ( Timestamp ) + direct_messages.sort_by(|a, b| a.1.cmp(&b.1)); + } + + direct_messages +} + +pub async fn get_orders_list( + pubkey: PublicKey, + status: Status, + currency: Option, + kind: Option, + client: &Client, +) -> Result> { + let since_time = chrono::Utc::now() + .checked_sub_signed(chrono::Duration::days(7)) + .unwrap() + .timestamp() as u64; + + let timestamp = Timestamp::from(since_time); + + let filters = Filter::new() + .author(pubkey) + .limit(50) + .since(timestamp) + .custom_tag(SingleLetterTag::lowercase(Alphabet::Z), vec!["order"]) + .kind(Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND)); + + info!( + "Request to mostro id : {:?} with event kind : {:?} ", + filters.authors, filters.kinds + ); + + // Extracted Orders List + let mut complete_events_list = Vec::::new(); + let mut requested_orders_list = Vec::::new(); + + // Send all requests to relays + if let Ok(mostro_req) = client + .fetch_events(vec![filters], Duration::from_secs(15)) + .await + { + // Scan events to extract all orders + for el in mostro_req.iter() { + let order = order_from_tags(el.tags.clone()); + + if order.is_err() { + error!("{order:?}"); + continue; + } + let mut order = order?; + + info!("Found Order id : {:?}", order.id.unwrap()); + + if order.id.is_none() { + info!("Order ID is none"); + continue; + } + + if order.kind.is_none() { + info!("Order kind is none"); + continue; + } + + if order.status.is_none() { + info!("Order status is none"); + continue; + } + + // Get created at field from Nostr event + order.created_at = Some(el.created_at.as_u64() as i64); + + complete_events_list.push(order.clone()); + + if order.status.ne(&Some(status)) { + continue; + } + + if currency.is_some() && order.fiat_code.ne(¤cy.clone().unwrap()) { + continue; + } + + if kind.is_some() && order.kind.ne(&kind) { + continue; + } + // Add just requested orders requested by filtering + requested_orders_list.push(order); + } + } + + // Order all element ( orders ) received to filter - discard disaligned messages + // if an order has an older message with the state we received is discarded for the latest one + requested_orders_list.retain(|keep| { + !complete_events_list + .iter() + .any(|x| x.id == keep.id && x.created_at > keep.created_at) + }); + // Sort by id to remove duplicates + requested_orders_list.sort_by(|a, b| b.id.cmp(&a.id)); + requested_orders_list.dedup_by(|a, b| a.id == b.id); + + // Finally sort list by creation time + requested_orders_list.sort_by(|a, b| b.created_at.cmp(&a.created_at)); + + Ok(requested_orders_list) +} + +pub async fn get_disputes_list(pubkey: PublicKey, client: &Client) -> Result> { + let since_time = chrono::Utc::now() + .checked_sub_signed(chrono::Duration::days(7)) + .unwrap() + .timestamp() as u64; + + let timestamp = Timestamp::from(since_time); + + let filter = Filter::new() + .author(pubkey) + .limit(50) + .since(timestamp) + .custom_tag(SingleLetterTag::lowercase(Alphabet::Z), vec!["dispute"]) + .kind(Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND)); + + // Extracted Orders List + let mut disputes_list = Vec::::new(); + + // Send all requests to relays + if let Ok(mostro_req) = client + .fetch_events(vec![filter], Duration::from_secs(15)) + .await + { + // Scan events to extract all disputes + for d in mostro_req.iter() { + let dispute = dispute_from_tags(d.tags.clone()); + + if dispute.is_err() { + error!("{dispute:?}"); + continue; + } + let mut dispute = dispute?; + + info!("Found Dispute id : {:?}", dispute.id); + + // Get created at field from Nostr event + dispute.created_at = d.created_at.as_u64() as i64; + disputes_list.push(dispute); + } + } + + let buffer_dispute_list = disputes_list.clone(); + // Order all element ( orders ) received to filter - discard disaligned messages + // if an order has an older message with the state we received is discarded for the latest one + disputes_list.retain(|keep| { + !buffer_dispute_list + .iter() + .any(|x| x.id == keep.id && x.created_at > keep.created_at) + }); + + // Sort by id to remove duplicates + disputes_list.sort_by(|a, b| b.id.cmp(&a.id)); + disputes_list.dedup_by(|a, b| a.id == b.id); + + // Finally sort list by creation time + disputes_list.sort_by(|a, b| b.created_at.cmp(&a.created_at)); + + Ok(disputes_list) +} + +/// Uppercase first letter of a string. +pub fn uppercase_first(s: &str) -> String { + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +pub fn get_mcli_path() -> String { + let home_dir = dirs::home_dir().expect("Couldn't get home directory"); + let mcli_path = format!("{}/.mcli", home_dir.display()); + if !Path::new(&mcli_path).exists() { + fs::create_dir(&mcli_path).expect("Couldn't create mostro-cli directory in HOME"); + println!("Directory {} created.", mcli_path); + } + + mcli_path +} diff --git a/static/logo.png b/mostro-cli/static/logo.png similarity index 100% rename from static/logo.png rename to mostro-cli/static/logo.png diff --git a/mostro-core/.github/workflows/rust.yml b/mostro-core/.github/workflows/rust.yml new file mode 100644 index 00000000..9fd45e09 --- /dev/null +++ b/mostro-core/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/mostro-core/Cargo.lock b/mostro-core/Cargo.lock new file mode 100644 index 00000000..d3e42cb9 --- /dev/null +++ b/mostro-core/Cargo.lock @@ -0,0 +1,2539 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "async-utility" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a349201d80b4aa18d17a34a182bdd7f8ddf845e9e57d2ea130a12e10ef1e3a47" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d50cb541e6d09e119e717c64c46ed33f49be7fa592fa805d56c11d6a7ff093c" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls 0.26.1", + "tokio-socks", + "tokio-tungstenite", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-destructor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d919cb60ba95c87ba42777e9e246c4e8d658057299b437b7512531ce0a09a23" +dependencies = [ + "tracing", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals 0.3.0", + "bitcoin_hashes 0.14.0", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bip39" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" +dependencies = [ + "bitcoin_hashes 0.13.0", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32", + "bitcoin-internals 0.3.0", + "bitcoin-io 0.1.3", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative 0.2.1", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b854212e29b96c8f0fe04cab11d57586c8f3257de0d146c76cb3b42b3eb9118" + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26792cd2bf245069a1c5acb06aa7ad7abe1de69b507c90b490bca81e0665d0ee" +dependencies = [ + "bitcoin-internals 0.4.0", +] + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals 0.3.0", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals 0.2.0", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io 0.1.3", + "hex-conservative 0.2.1", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0982261c82a50d89d1a411602afee0498b3e0debe3d36693f0c661352809639" +dependencies = [ + "bitcoin-io 0.2.0", + "hex-conservative 0.3.0", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.8", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +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 = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "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]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "libsqlite3-sys" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "mostro-core" +version = "0.6.21" +dependencies = [ + "bitcoin", + "bitcoin_hashes 0.15.0", + "nostr-sdk", + "serde", + "serde_json", + "sqlx", + "sqlx-crud", + "uuid", + "wasm-bindgen", +] + +[[package]] +name = "negentropy" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" + +[[package]] +name = "negentropy" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a88da9dd148bbcdce323dd6ac47d369b4769d4a3b78c6c52389b9269f77932" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nostr" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aad4b767bbed24ac5eb4465bfb83bc1210522eb99d67cf4e547ec2ec7e47786" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bech32", + "bip39", + "bitcoin", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom", + "instant", + "negentropy 0.3.1", + "negentropy 0.4.3", + "once_cell", + "scrypt", + "serde", + "serde_json", + "unicode-normalization", + "url", +] + +[[package]] +name = "nostr-database" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23696338d51e45cd44e061823847f4b0d1d362eca80d5033facf9c184149f72f" +dependencies = [ + "async-trait", + "lru", + "nostr", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nostr-relay-pool" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15fcc6e3f0ca54d0fc779009bc5f2684cea9147be3b6aa68a7d301ea590f95f5" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "negentropy 0.3.1", + "negentropy 0.4.3", + "nostr", + "nostr-database", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "nostr-sdk" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "491221fc89b1aa189a0de640127127d68b4e7c5c1d44371b04d9a6d10694b5af" +dependencies = [ + "async-utility", + "atomic-destructor", + "nostr", + "nostr-database", + "nostr-relay-pool", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.23.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "indexmap 2.7.0", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +dependencies = [ + "ahash 0.7.8", + "atoi", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "indexmap 1.9.3", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls 0.20.9", + "rustls-pemfile", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "uuid", + "webpki-roots 0.22.6", +] + +[[package]] +name = "sqlx-crud" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00cbbfdea4be98477e9b5b7190b9e2b1e567e2c0b6c2649b6b6622cfffec50e" +dependencies = [ + "futures", + "sqlx", + "sqlx-crud-macros", + "thiserror", +] + +[[package]] +name = "sqlx-crud-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f8aaa082d86752ecd74230711220872649c2b3ef43186d1beb06a14fdf566fe" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +dependencies = [ + "dotenvy", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn 1.0.109", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.23.4", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.20", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.20", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.1", + "tungstenite", + "webpki-roots 0.26.7", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls 0.23.20", + "rustls-pki-types", + "sha1", + "thiserror", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +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 = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", + "rand", + "serde", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b91f57fe13a38d0ce9e28a03463d8d3c2468ed03d75375110ec71d93b449a08" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" + +[[package]] +name = "web-sys" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[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 = "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 = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "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]] +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/mostro-core/Cargo.toml b/mostro-core/Cargo.toml new file mode 100644 index 00000000..a0d221d4 --- /dev/null +++ b/mostro-core/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "mostro-core" +version = "0.6.21" +edition = "2021" +license = "MIT" +authors = ["Francisco Calderón "] +description = "Mostro Core library" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +anyhow = { workspace = true } +chrono = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +uuid = { workspace = true } +sqlx = { workspace = true, optional = true } +sqlx-crud = { workspace = true, optional = true } +wasm-bindgen = { version = "0.2.92", optional = true } +bitcoin = "0.32.5" +bitcoin_hashes = "0.15.0" +nostr-sdk = { workspace = true } + + +[features] +default = ["wasm"] +wasm = ["dep:wasm-bindgen"] +sqlx = ["dep:wasm-bindgen", "dep:sqlx", "dep:sqlx-crud"] diff --git a/mostro-core/LICENSE b/mostro-core/LICENSE new file mode 100644 index 00000000..a4897774 --- /dev/null +++ b/mostro-core/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Francisco Calderón + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mostro-core/README.md b/mostro-core/README.md new file mode 100644 index 00000000..09edfa19 --- /dev/null +++ b/mostro-core/README.md @@ -0,0 +1 @@ +# Mostro core lib diff --git a/mostro-core/rust-toolchain.toml b/mostro-core/rust-toolchain.toml new file mode 100644 index 00000000..1173a45a --- /dev/null +++ b/mostro-core/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.82.0" +profile = "minimal" +components = ["clippy", "rust-docs", "rustfmt"] +targets = ["wasm32-unknown-unknown"] \ No newline at end of file diff --git a/mostro-core/src/dispute.rs b/mostro-core/src/dispute.rs new file mode 100644 index 00000000..f7a1062d --- /dev/null +++ b/mostro-core/src/dispute.rs @@ -0,0 +1,82 @@ +use chrono::Utc; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "sqlx")] +use sqlx::{FromRow, Type}; +#[cfg(feature = "sqlx")] +use sqlx_crud::SqlxCrud; +use std::{fmt::Display, str::FromStr}; +use uuid::Uuid; + +/// Each status that a dispute can have +#[cfg_attr(feature = "sqlx", derive(Type))] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum Status { + /// Dispute initiated and waiting to be taken by a solver + #[default] + Initiated, + /// Taken by a solver + InProgress, + /// Canceled by admin/solver and refunded to seller + SellerRefunded, + /// Settled seller's invoice by admin/solver and started to pay sats to buyer + Settled, + /// Released by the seller + Released, +} + +impl Display for Status { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Status::Initiated => write!(f, "initiated"), + Status::InProgress => write!(f, "in-progress"), + Status::SellerRefunded => write!(f, "seller-refunded"), + Status::Settled => write!(f, "settled"), + Status::Released => write!(f, "released"), + } + } +} + +impl FromStr for Status { + type Err = (); + + fn from_str(s: &str) -> std::result::Result { + match s { + "initiated" => std::result::Result::Ok(Self::Initiated), + "in-progress" => std::result::Result::Ok(Self::InProgress), + "seller-refunded" => std::result::Result::Ok(Self::SellerRefunded), + "settled" => std::result::Result::Ok(Self::Settled), + "released" => std::result::Result::Ok(Self::Released), + _ => Err(()), + } + } +} + +/// Database representation of a dispute +#[cfg_attr(feature = "sqlx", derive(FromRow, SqlxCrud), external_id)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)] +pub struct Dispute { + pub id: Uuid, + pub order_id: Uuid, + pub status: String, + pub solver_pubkey: Option, + pub created_at: i64, + pub taken_at: i64, + pub buyer_token: Option, + pub seller_token: Option, +} + +impl Dispute { + pub fn new(order_id: Uuid) -> Self { + Self { + id: Uuid::new_v4(), + order_id, + status: Status::Initiated.to_string(), + solver_pubkey: None, + created_at: Utc::now().timestamp(), + taken_at: 0, + buyer_token: None, + seller_token: None, + } + } +} diff --git a/mostro-core/src/lib.rs b/mostro-core/src/lib.rs new file mode 100644 index 00000000..8659ef69 --- /dev/null +++ b/mostro-core/src/lib.rs @@ -0,0 +1,183 @@ +pub mod dispute; +pub mod message; +pub mod order; +pub mod rating; +pub mod user; + +/// All events broadcasted by Mostro daemon are Parameterized Replaceable Events +/// and the event kind must be between 30000 and 39999 +pub const NOSTR_REPLACEABLE_EVENT_KIND: u16 = 38383; +pub const PROTOCOL_VER: u8 = 1; + +#[cfg(test)] +mod test { + use crate::message::{Action, CantDoReason, Message, MessageKind, Payload, Peer}; + use crate::order::{Kind, SmallOrder, Status}; + use nostr_sdk::Keys; + use uuid::uuid; + + #[test] + fn test_status_string() { + assert_eq!(Status::Active.to_string(), "active"); + assert_eq!(Status::CompletedByAdmin.to_string(), "completed-by-admin"); + assert_eq!(Status::FiatSent.to_string(), "fiat-sent"); + assert_ne!(Status::Pending.to_string(), "Pending"); + } + + #[test] + fn test_kind_string() { + assert_ne!(Kind::Sell.to_string(), "active"); + assert_eq!(Kind::Sell.to_string(), "sell"); + assert_eq!(Kind::Buy.to_string(), "buy"); + assert_ne!(Kind::Buy.to_string(), "active"); + } + + #[test] + fn test_order_message() { + let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23"); + let payload = Payload::Order(SmallOrder::new( + Some(uuid), + Some(Kind::Sell), + Some(Status::Pending), + 100, + "eur".to_string(), + None, + None, + 100, + "SEPA".to_string(), + 1, + None, + None, + None, + Some(1627371434), + None, + None, + None, + )); + + let test_message = Message::Order(MessageKind::new( + Some(uuid), + Some(1), + Some(2), + Action::NewOrder, + Some(payload), + )); + let test_message_json = test_message.as_json().unwrap(); + let sample_message = r#"{"order":{"version":1,"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","request_id":1,"trade_index":2,"action":"new-order","payload":{"order":{"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","kind":"sell","status":"pending","amount":100,"fiat_code":"eur","fiat_amount":100,"payment_method":"SEPA","premium":1,"created_at":1627371434}}}}"#; + let message = Message::from_json(sample_message).unwrap(); + assert!(message.verify()); + let message_json = message.as_json().unwrap(); + assert_eq!(message_json, test_message_json); + } + + #[test] + fn test_payment_request_payload_message() { + let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23"); + let test_message = Message::Order(MessageKind::new( + Some(uuid), + Some(1), + Some(3), + Action::PayInvoice, + Some(Payload::PaymentRequest( + Some(SmallOrder::new( + Some(uuid), + Some(Kind::Sell), + Some(Status::WaitingPayment), + 100, + "eur".to_string(), + None, + None, + 100, + "SEPA".to_string(), + 1, + None, + None, + None, + Some(1627371434), + None, + None, + None, + )), + "lnbcrt78510n1pj59wmepp50677g8tffdqa2p8882y0x6newny5vtz0hjuyngdwv226nanv4uzsdqqcqzzsxqyz5vqsp5skn973360gp4yhlpmefwvul5hs58lkkl3u3ujvt57elmp4zugp4q9qyyssqw4nzlr72w28k4waycf27qvgzc9sp79sqlw83j56txltz4va44j7jda23ydcujj9y5k6k0rn5ms84w8wmcmcyk5g3mhpqepf7envhdccp72nz6e".to_string(), + None, + )), + )); + let sample_message = r#"{"order":{"version":1,"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","request_id":1,"trade_index":3,"action":"pay-invoice","payload":{"payment_request":[{"id":"308e1272-d5f4-47e6-bd97-3504baea9c23","kind":"sell","status":"waiting-payment","amount":100,"fiat_code":"eur","fiat_amount":100,"payment_method":"SEPA","premium":1,"created_at":1627371434},"lnbcrt78510n1pj59wmepp50677g8tffdqa2p8882y0x6newny5vtz0hjuyngdwv226nanv4uzsdqqcqzzsxqyz5vqsp5skn973360gp4yhlpmefwvul5hs58lkkl3u3ujvt57elmp4zugp4q9qyyssqw4nzlr72w28k4waycf27qvgzc9sp79sqlw83j56txltz4va44j7jda23ydcujj9y5k6k0rn5ms84w8wmcmcyk5g3mhpqepf7envhdccp72nz6e",null]}}}"#; + let message = Message::from_json(sample_message).unwrap(); + assert!(message.verify()); + let message_json = message.as_json().unwrap(); + let test_message_json = test_message.as_json().unwrap(); + assert_eq!(message_json, test_message_json); + } + + #[test] + fn test_message_payload_signature() { + let uuid = uuid!("308e1272-d5f4-47e6-bd97-3504baea9c23"); + let peer = Peer::new( + "npub1testjsf0runcqdht5apkfcalajxkf8txdxqqk5kgm0agc38ke4vsfsgzf8".to_string(), + ); + let payload = Payload::Peer(peer); + let test_message = Message::Order(MessageKind::new( + Some(uuid), + Some(1), + Some(2), + Action::FiatSentOk, + Some(payload), + )); + assert!(test_message.verify()); + // Message should be signed with the trade keys + let trade_keys = + Keys::parse("110e43647eae221ab1da33ddc17fd6ff423f2b2f49d809b9ffa40794a2ab996c") + .unwrap(); + let sig = test_message.get_inner_message_kind().sign(&trade_keys); + + assert!(test_message + .get_inner_message_kind() + .verify_signature(trade_keys.public_key(), sig)); + } + + #[test] + fn test_cant_do_message_serialization() { + // Test all CantDoReason variants + let reasons = vec![ + CantDoReason::InvalidSignature, + CantDoReason::InvalidTradeIndex, + CantDoReason::InvalidAmount, + CantDoReason::InvalidInvoice, + CantDoReason::InvalidPaymentRequest, + CantDoReason::InvalidPeer, + CantDoReason::InvalidRating, + CantDoReason::InvalidTextMessage, + CantDoReason::InvalidOrderStatus, + CantDoReason::InvalidPubkey, + CantDoReason::InvalidParameters, + CantDoReason::OrderAlreadyCanceled, + CantDoReason::CantCreateUser, + ]; + + for reason in reasons { + let cant_do = Message::CantDo(MessageKind::new( + None, + None, + None, + Action::CantDo, + Some(Payload::CantDo(Some(reason.clone()))), + )); + let message = Message::from_json(&cant_do.as_json().unwrap()).unwrap(); + assert!(message.verify()); + assert_eq!(message.as_json().unwrap(), cant_do.as_json().unwrap()); + } + + // Test None case + let cant_do = Message::CantDo(MessageKind::new( + None, + None, + None, + Action::CantDo, + Some(Payload::CantDo(None)), + )); + let message = Message::from_json(&cant_do.as_json().unwrap()).unwrap(); + assert!(message.verify()); + assert_eq!(message.as_json().unwrap(), cant_do.as_json().unwrap()); + } +} diff --git a/mostro-core/src/message.rs b/mostro-core/src/message.rs new file mode 100644 index 00000000..3e06536f --- /dev/null +++ b/mostro-core/src/message.rs @@ -0,0 +1,425 @@ +use crate::order::SmallOrder; +use crate::PROTOCOL_VER; +use anyhow::{Ok, Result}; +use bitcoin::hashes::sha256::Hash as Sha256Hash; +use bitcoin::hashes::Hash; +use bitcoin::key::Secp256k1; +use bitcoin::secp256k1::Message as BitcoinMessage; +use nostr_sdk::prelude::*; +use serde::{Deserialize, Serialize}; +use std::fmt; +use uuid::Uuid; + +/// One party of the trade +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Peer { + pub pubkey: String, +} + +impl Peer { + pub fn new(pubkey: String) -> Self { + Self { pubkey } + } + + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + + pub fn as_json(&self) -> Result { + Ok(serde_json::to_string(&self)?) + } +} + +/// Action is used to identify each message between Mostro and users +#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone)] +#[serde(rename_all = "kebab-case")] +pub enum Action { + NewOrder, + TakeSell, + TakeBuy, + PayInvoice, + FiatSent, + FiatSentOk, + Release, + Released, + Cancel, + Canceled, + CooperativeCancelInitiatedByYou, + CooperativeCancelInitiatedByPeer, + DisputeInitiatedByYou, + DisputeInitiatedByPeer, + CooperativeCancelAccepted, + BuyerInvoiceAccepted, + PurchaseCompleted, + HoldInvoicePaymentAccepted, + HoldInvoicePaymentSettled, + HoldInvoicePaymentCanceled, + WaitingSellerToPay, + WaitingBuyerInvoice, + AddInvoice, + BuyerTookOrder, + Rate, + RateUser, + RateReceived, + CantDo, + Dispute, + AdminCancel, + AdminCanceled, + AdminSettle, + AdminSettled, + AdminAddSolver, + AdminTakeDispute, + AdminTookDispute, + IsNotYourOrder, + NotAllowedByStatus, + OutOfRangeFiatAmount, + IsNotYourDispute, + NotFound, + IncorrectInvoiceAmount, + InvalidSatsAmount, + OutOfRangeSatsAmount, + PaymentFailed, + InvoiceUpdated, + SendDm, +} + +impl fmt::Display for Action { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self:?}") + } +} + +/// Use this Message to establish communication between users and Mostro +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub enum Message { + Order(MessageKind), + Dispute(MessageKind), + CantDo(MessageKind), + Rate(MessageKind), + Dm(MessageKind), +} + +impl Message { + /// New order message + pub fn new_order( + id: Option, + request_id: Option, + trade_index: Option, + action: Action, + payload: Option, + ) -> Self { + let kind = MessageKind::new(id, request_id, trade_index, action, payload); + Self::Order(kind) + } + + /// New dispute message + pub fn new_dispute( + id: Option, + request_id: Option, + trade_index: Option, + action: Action, + payload: Option, + ) -> Self { + let kind = MessageKind::new(id, request_id, trade_index, action, payload); + + Self::Dispute(kind) + } + + /// New can't do template message message + pub fn cant_do(id: Option, request_id: Option, payload: Option) -> Self { + let kind = MessageKind::new(id, request_id, None, Action::CantDo, payload); + + Self::CantDo(kind) + } + + /// New DM message + pub fn new_dm( + id: Option, + request_id: Option, + action: Action, + payload: Option, + ) -> Self { + let kind = MessageKind::new(id, request_id, None, action, payload); + + Self::Dm(kind) + } + + /// Get message from json string + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + + /// Get message as json string + pub fn as_json(&self) -> Result { + Ok(serde_json::to_string(&self)?) + } + + // Get inner message kind + pub fn get_inner_message_kind(&self) -> &MessageKind { + match self { + Message::Dispute(k) + | Message::Order(k) + | Message::CantDo(k) + | Message::Rate(k) + | Message::Dm(k) => k, + } + } + + // Get action from the inner message + pub fn inner_action(&self) -> Option { + match self { + Message::Dispute(a) + | Message::Order(a) + | Message::CantDo(a) + | Message::Rate(a) + | Message::Dm(a) => Some(a.get_action()), + } + } + + /// Verify if is valid the inner message + pub fn verify(&self) -> bool { + match self { + Message::Order(m) + | Message::Dispute(m) + | Message::CantDo(m) + | Message::Rate(m) + | Message::Dm(m) => m.verify(), + } + } +} + +/// Use this Message to establish communication between users and Mostro +#[derive(Debug, Deserialize, Serialize)] +pub struct MessageKind { + /// Message version + pub version: u8, + /// Request_id for test on client + pub request_id: Option, + /// Trade key index + pub trade_index: Option, + /// Message id is not mandatory + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + /// Action to be taken + pub action: Action, + /// Payload of the Message + pub payload: Option, +} + +type Amount = i64; + +/// Represents specific reasons why a requested action cannot be performed +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum CantDoReason { + /// The provided signature is invalid or missing + InvalidSignature, + /// The specified trade index does not exist or is invalid + InvalidTradeIndex, + /// The provided amount is invalid or out of acceptable range + InvalidAmount, + /// The provided invoice is malformed or expired + InvalidInvoice, + /// The payment request is invalid or cannot be processed + InvalidPaymentRequest, + /// The specified peer is invalid or not found + InvalidPeer, + /// The rating value is invalid or out of range + InvalidRating, + /// The text message is invalid or contains prohibited content + InvalidTextMessage, + /// The order kind is invalid + InvalidOrderKind, + /// The order status is invalid + InvalidOrderStatus, + /// Invalid pubkey + InvalidPubkey, + /// Invalid parameters + InvalidParameters, + /// The order is already canceled + OrderAlreadyCanceled, + /// Can't create user + CantCreateUser, +} + +/// Message payload +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(rename_all = "snake_case")] +pub enum Payload { + Order(SmallOrder), + PaymentRequest(Option, String, Option), + TextMessage(String), + Peer(Peer), + RatingUser(u8), + Amount(Amount), + Dispute(Uuid, Option), + CantDo(Option), +} + +#[allow(dead_code)] +impl MessageKind { + /// New message + pub fn new( + id: Option, + request_id: Option, + trade_index: Option, + action: Action, + payload: Option, + ) -> Self { + Self { + version: PROTOCOL_VER, + request_id, + trade_index, + id, + action, + payload, + } + } + /// Get message from json string + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + /// Get message as json string + pub fn as_json(&self) -> Result { + Ok(serde_json::to_string(&self)?) + } + + // Get action from the inner message + pub fn get_action(&self) -> Action { + self.action.clone() + } + + /// Verify if is valid message + pub fn verify(&self) -> bool { + match &self.action { + Action::NewOrder => matches!(&self.payload, Some(Payload::Order(_))), + Action::PayInvoice | Action::AddInvoice => { + if self.id.is_none() { + return false; + } + matches!(&self.payload, Some(Payload::PaymentRequest(_, _, _))) + } + Action::TakeSell + | Action::TakeBuy + | Action::FiatSent + | Action::FiatSentOk + | Action::Release + | Action::Released + | Action::Dispute + | Action::AdminCancel + | Action::AdminCanceled + | Action::AdminSettle + | Action::AdminSettled + | Action::Rate + | Action::RateReceived + | Action::AdminTakeDispute + | Action::AdminTookDispute + | Action::DisputeInitiatedByYou + | Action::DisputeInitiatedByPeer + | Action::WaitingBuyerInvoice + | Action::PurchaseCompleted + | Action::HoldInvoicePaymentAccepted + | Action::HoldInvoicePaymentSettled + | Action::HoldInvoicePaymentCanceled + | Action::WaitingSellerToPay + | Action::BuyerTookOrder + | Action::BuyerInvoiceAccepted + | Action::CooperativeCancelInitiatedByYou + | Action::CooperativeCancelInitiatedByPeer + | Action::CooperativeCancelAccepted + | Action::Cancel + | Action::IsNotYourOrder + | Action::NotAllowedByStatus + | Action::OutOfRangeFiatAmount + | Action::OutOfRangeSatsAmount + | Action::IsNotYourDispute + | Action::NotFound + | Action::IncorrectInvoiceAmount + | Action::InvalidSatsAmount + | Action::PaymentFailed + | Action::InvoiceUpdated + | Action::AdminAddSolver + | Action::SendDm + | Action::Canceled => { + if self.id.is_none() { + return false; + } + true + } + Action::RateUser => { + matches!(&self.payload, Some(Payload::RatingUser(_))) + } + Action::CantDo => { + matches!(&self.payload, Some(Payload::CantDo(_))) + } + } + } + + pub fn get_order(&self) -> Option<&SmallOrder> { + if self.action != Action::NewOrder { + return None; + } + match &self.payload { + Some(Payload::Order(o)) => Some(o), + _ => None, + } + } + + pub fn get_payment_request(&self) -> Option { + if self.action != Action::TakeSell + && self.action != Action::AddInvoice + && self.action != Action::NewOrder + { + return None; + } + match &self.payload { + Some(Payload::PaymentRequest(_, pr, _)) => Some(pr.to_owned()), + Some(Payload::Order(ord)) => ord.buyer_invoice.to_owned(), + _ => None, + } + } + + pub fn get_amount(&self) -> Option { + if self.action != Action::TakeSell && self.action != Action::TakeBuy { + return None; + } + match &self.payload { + Some(Payload::PaymentRequest(_, _, amount)) => *amount, + Some(Payload::Amount(amount)) => Some(*amount), + _ => None, + } + } + + pub fn get_payload(&self) -> Option<&Payload> { + self.payload.as_ref() + } + + pub fn has_trade_index(&self) -> (bool, i64) { + if let Some(index) = self.trade_index { + return (true, index); + } + (false, 0) + } + + pub fn sign(&self, keys: &Keys) -> Signature { + let message = self.as_json().unwrap(); + let hash: Sha256Hash = Sha256Hash::hash(message.as_bytes()); + let hash = hash.to_byte_array(); + let message: BitcoinMessage = BitcoinMessage::from_digest(hash); + + keys.sign_schnorr(&message) + } + + pub fn verify_signature(&self, pubkey: PublicKey, sig: Signature) -> bool { + // Create message hash + let message = self.as_json().unwrap(); + let hash: Sha256Hash = Sha256Hash::hash(message.as_bytes()); + let hash = hash.to_byte_array(); + let message: BitcoinMessage = BitcoinMessage::from_digest(hash); + // Create a verification-only context for better performance + let secp = Secp256k1::verification_only(); + // Verify signature + pubkey.verify(&secp, &message, &sig).is_ok() + } +} diff --git a/mostro-core/src/order.rs b/mostro-core/src/order.rs new file mode 100644 index 00000000..7f4e3831 --- /dev/null +++ b/mostro-core/src/order.rs @@ -0,0 +1,274 @@ +use anyhow::{Ok, Result}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "sqlx")] +use sqlx::FromRow; +#[cfg(feature = "sqlx")] +use sqlx_crud::SqlxCrud; +use std::{fmt::Display, str::FromStr}; +use uuid::Uuid; +use wasm_bindgen::prelude::*; + +/// Orders can be only Buy or Sell +#[wasm_bindgen] +#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum Kind { + Buy, + Sell, +} + +impl FromStr for Kind { + type Err = (); + + fn from_str(kind: &str) -> std::result::Result { + match kind.to_lowercase().as_str() { + "buy" => std::result::Result::Ok(Self::Buy), + "sell" => std::result::Result::Ok(Self::Sell), + _ => Err(()), + } + } +} + +impl Display for Kind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Kind::Sell => write!(f, "sell"), + Kind::Buy => write!(f, "buy"), + } + } +} + +/// Each status that an order can have +#[wasm_bindgen] +#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum Status { + Active, + Canceled, + CanceledByAdmin, + SettledByAdmin, + CompletedByAdmin, + Dispute, + Expired, + FiatSent, + SettledHoldInvoice, + Pending, + Success, + WaitingBuyerInvoice, + WaitingPayment, + CooperativelyCanceled, +} + +impl Display for Status { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Status::Active => write!(f, "active"), + Status::Canceled => write!(f, "canceled"), + Status::CanceledByAdmin => write!(f, "canceled-by-admin"), + Status::SettledByAdmin => write!(f, "settled-by-admin"), + Status::CompletedByAdmin => write!(f, "completed-by-admin"), + Status::Dispute => write!(f, "dispute"), + Status::Expired => write!(f, "expired"), + Status::FiatSent => write!(f, "fiat-sent"), + Status::SettledHoldInvoice => write!(f, "settled-hold-invoice"), + Status::Pending => write!(f, "pending"), + Status::Success => write!(f, "success"), + Status::WaitingBuyerInvoice => write!(f, "waiting-buyer-invoice"), + Status::WaitingPayment => write!(f, "waiting-payment"), + Status::CooperativelyCanceled => write!(f, "cooperatively-canceled"), + } + } +} + +impl FromStr for Status { + type Err = (); + + fn from_str(s: &str) -> std::result::Result { + match s.to_lowercase().as_str() { + "active" => std::result::Result::Ok(Self::Active), + "canceled" => std::result::Result::Ok(Self::Canceled), + "canceled-by-admin" => std::result::Result::Ok(Self::CanceledByAdmin), + "settled-by-admin" => std::result::Result::Ok(Self::SettledByAdmin), + "completed-by-admin" => std::result::Result::Ok(Self::CompletedByAdmin), + "dispute" => std::result::Result::Ok(Self::Dispute), + "expired" => std::result::Result::Ok(Self::Expired), + "fiat-sent" => std::result::Result::Ok(Self::FiatSent), + "settled-hold-invoice" => std::result::Result::Ok(Self::SettledHoldInvoice), + "pending" => std::result::Result::Ok(Self::Pending), + "success" => std::result::Result::Ok(Self::Success), + "waiting-buyer-invoice" => std::result::Result::Ok(Self::WaitingBuyerInvoice), + "waiting-payment" => std::result::Result::Ok(Self::WaitingPayment), + "cooperatively-canceled" => std::result::Result::Ok(Self::CooperativelyCanceled), + _ => Err(()), + } + } +} + +/// Database representation of an order +#[cfg_attr(feature = "sqlx", derive(FromRow, SqlxCrud), external_id)] +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct Order { + pub id: Uuid, + pub kind: String, + pub event_id: String, + pub hash: Option, + pub preimage: Option, + pub creator_pubkey: String, + pub cancel_initiator_pubkey: Option, + pub buyer_pubkey: Option, + pub master_buyer_pubkey: Option, + pub seller_pubkey: Option, + pub master_seller_pubkey: Option, + pub status: String, + pub price_from_api: bool, + pub premium: i64, + pub payment_method: String, + pub amount: i64, + pub min_amount: Option, + pub max_amount: Option, + pub buyer_dispute: bool, + pub seller_dispute: bool, + pub buyer_cooperativecancel: bool, + pub seller_cooperativecancel: bool, + pub fee: i64, + pub routing_fee: i64, + pub fiat_code: String, + pub fiat_amount: i64, + pub buyer_invoice: Option, + pub range_parent_id: Option, + pub invoice_held_at: i64, + pub taken_at: i64, + pub created_at: i64, + pub buyer_sent_rate: bool, + pub seller_sent_rate: bool, + pub failed_payment: bool, + pub payment_attempts: i64, + pub expires_at: i64, + pub trade_index_seller: Option, + pub trade_index_buyer: Option, +} + +impl Order { + pub fn as_new_order(&self) -> SmallOrder { + SmallOrder::new( + Some(self.id), + Some(Kind::from_str(&self.kind).unwrap()), + Some(Status::from_str(&self.status).unwrap()), + self.amount, + self.fiat_code.clone(), + self.min_amount, + self.max_amount, + self.fiat_amount, + self.payment_method.clone(), + self.premium, + None, + None, + self.buyer_invoice.clone(), + Some(self.created_at), + Some(self.expires_at), + None, + None, + ) + } + + pub fn is_range_order(&self) -> bool { + self.min_amount.is_some() && self.max_amount.is_some() + } +} + +/// We use this struct to create a new order +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct SmallOrder { + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + pub kind: Option, + pub status: Option, + pub amount: i64, + pub fiat_code: String, + pub min_amount: Option, + pub max_amount: Option, + pub fiat_amount: i64, + pub payment_method: String, + pub premium: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub buyer_trade_pubkey: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub seller_trade_pubkey: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub buyer_invoice: Option, + pub created_at: Option, + pub expires_at: Option, + pub buyer_token: Option, + pub seller_token: Option, +} + +#[allow(dead_code)] +impl SmallOrder { + #[allow(clippy::too_many_arguments)] + pub fn new( + id: Option, + kind: Option, + status: Option, + amount: i64, + fiat_code: String, + min_amount: Option, + max_amount: Option, + fiat_amount: i64, + payment_method: String, + premium: i64, + buyer_trade_pubkey: Option, + seller_trade_pubkey: Option, + buyer_invoice: Option, + created_at: Option, + expires_at: Option, + buyer_token: Option, + seller_token: Option, + ) -> Self { + Self { + id, + kind, + status, + amount, + fiat_code, + min_amount, + max_amount, + fiat_amount, + payment_method, + premium, + buyer_trade_pubkey, + seller_trade_pubkey, + buyer_invoice, + created_at, + expires_at, + buyer_token, + seller_token, + } + } + /// New order from json string + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + + /// Get order as json string + pub fn as_json(&self) -> Result { + Ok(serde_json::to_string(&self)?) + } + + // Get the amount of sats or the string "Market price" + pub fn sats_amount(&self) -> String { + if self.amount == 0 { + "Market price".to_string() + } else { + self.amount.to_string() + } + } + + // Get the fiat amount, if the order is a range order, return the range as min-max string + pub fn fiat_amount(&self) -> String { + if self.max_amount.is_some() { + format!("{}-{}", self.min_amount.unwrap(), self.max_amount.unwrap()) + } else { + self.fiat_amount.to_string() + } + } +} diff --git a/mostro-core/src/rating.rs b/mostro-core/src/rating.rs new file mode 100644 index 00000000..ec8827dc --- /dev/null +++ b/mostro-core/src/rating.rs @@ -0,0 +1,108 @@ +use anyhow::{Ok, Result}; +use nostr_sdk::prelude::*; +use serde::{Deserialize, Serialize}; + +/// We use this struct to create a user reputation +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Rating { + pub total_reviews: u64, + pub total_rating: f64, + pub last_rating: u8, + pub max_rate: u8, + pub min_rate: u8, +} + +impl Rating { + pub fn new( + total_reviews: u64, + total_rating: f64, + last_rating: u8, + min_rate: u8, + max_rate: u8, + ) -> Self { + Self { + total_reviews, + total_rating, + last_rating, + min_rate, + max_rate, + } + } + + /// New order from json string + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + + /// Get order as json string + pub fn as_json(&self) -> Result { + Ok(serde_json::to_string(&self)?) + } + + /// Transform Rating struct to tuple vector to easily interact with Nostr + pub fn to_tags(&self) -> Result { + let tags = vec![ + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("total_reviews")), + vec![self.total_reviews.to_string()], + ), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("total_rating")), + vec![self.total_rating.to_string()], + ), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("last_rating")), + vec![self.last_rating.to_string()], + ), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("max_rate")), + vec![self.max_rate.to_string()], + ), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("min_rate")), + vec![self.min_rate.to_string()], + ), + Tag::custom( + TagKind::Custom(std::borrow::Cow::Borrowed("z")), + vec!["rating".to_string()], + ), + ]; + + Ok(Tags::new(tags)) + } + + /// Transform tuple vector to Rating struct + pub fn from_tags(tags: Tags) -> Result { + let mut total_reviews = 0; + let mut total_rating = 0.0; + let mut last_rating = 0; + let mut max_rate = 0; + let mut min_rate = 0; + + for tag in tags.into_iter() { + let t = tag.to_vec(); + let key = t + .first() + .ok_or_else(|| anyhow::anyhow!("Missing tag key"))?; + let value = t + .get(1) + .ok_or_else(|| anyhow::anyhow!("Missing tag value"))?; + match key.as_str() { + "total_reviews" => total_reviews = value.parse::()?, + "total_rating" => total_rating = value.parse::()?, + "last_rating" => last_rating = value.parse::()?, + "max_rate" => max_rate = value.parse::()?, + "min_rate" => min_rate = value.parse::()?, + _ => {} + } + } + + Ok(Self { + total_reviews, + total_rating, + last_rating, + max_rate, + min_rate, + }) + } +} diff --git a/mostro-core/src/user.rs b/mostro-core/src/user.rs new file mode 100644 index 00000000..1e50f136 --- /dev/null +++ b/mostro-core/src/user.rs @@ -0,0 +1,50 @@ +use chrono::Utc; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "sqlx")] +use sqlx::FromRow; + +/// Database representation of an user +#[cfg_attr(feature = "sqlx", derive(FromRow))] +#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)] +pub struct User { + pub pubkey: String, + pub is_admin: i64, + pub is_solver: i64, + pub is_banned: i64, + pub category: i64, + /// We have to be sure that when a user creates a new order (or takes an order), + /// the trade_index is greater than the one we have in database + pub last_trade_index: i64, + pub total_reviews: i64, + pub total_rating: f64, + pub last_rating: i64, + pub max_rating: i64, + pub min_rating: i64, + pub created_at: i64, +} + +impl User { + pub fn new( + pubkey: String, + is_admin: i64, + is_solver: i64, + is_banned: i64, + category: i64, + trade_index: i64, + ) -> Self { + Self { + pubkey, + is_admin, + is_solver, + is_banned, + category, + last_trade_index: trade_index, + total_reviews: 0, + total_rating: 0.0, + last_rating: 0, + max_rating: 0, + min_rating: 0, + created_at: Utc::now().timestamp(), + } + } +} diff --git a/.github/workflows/rust.yml b/mostro/.github/workflows/rust.yml similarity index 100% rename from .github/workflows/rust.yml rename to mostro/.github/workflows/rust.yml diff --git a/CONTRIBUTING.md b/mostro/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to mostro/CONTRIBUTING.md diff --git a/mostro/Cargo.lock b/mostro/Cargo.lock new file mode 100644 index 00000000..0d9e913b --- /dev/null +++ b/mostro/Cargo.lock @@ -0,0 +1,4303 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "async-utility" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a349201d80b4aa18d17a34a182bdd7f8ddf845e9e57d2ea130a12e10ef1e3a47" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a107e3bdbe61e8e1e1341c57241b4b2d50501127b44bd2eff13b4635ab42d35a" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "thiserror", + "tokio", + "tokio-rustls 0.26.0", + "tokio-socks", + "tokio-tungstenite", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-destructor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d919cb60ba95c87ba42777e9e246c4e8d658057299b437b7512531ce0a09a23" +dependencies = [ + "tracing", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals 0.3.0", + "bitcoin_hashes 0.14.0", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bip39" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" +dependencies = [ + "bitcoin_hashes 0.13.0", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32 0.11.0", + "bitcoin-internals 0.3.0", + "bitcoin-io 0.1.3", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative 0.2.1", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b854212e29b96c8f0fe04cab11d57586c8f3257de0d146c76cb3b42b3eb9118" + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26792cd2bf245069a1c5acb06aa7ad7abe1de69b507c90b490bca81e0665d0ee" +dependencies = [ + "bitcoin-internals 0.4.0", +] + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals 0.3.0", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals 0.2.0", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io 0.1.3", + "hex-conservative 0.2.1", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0982261c82a50d89d1a411602afee0498b3e0debe3d36693f0c661352809639" +dependencies = [ + "bitcoin-io 0.2.0", + "hex-conservative 0.3.0", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust2", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc16" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crc8" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b31d2174830f395fd7e413c2f8a119252de36356982f805f495269331e97559e" + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "rand_core", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "easy-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91513ddb31553dbdf858a6ec344b1351ebf734a721d7df5e73ef10bad8494612" +dependencies = [ + "crc 1.8.1", + "crc16", + "crc8", + "md2", + "md4", + "md5", + "sha1 0.6.1", + "sha2 0.8.2", + "sha3", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] + +[[package]] +name = "email_address" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1019fa28f600f5b581b7a603d515c3f1635da041ca211b5055804788673abfe" +dependencies = [ + "serde", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fedimint-tonic-lnd" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df03ca33b5116de3051c1e233fe341e23b04c4913c7b16042497924559bc2a2e" +dependencies = [ + "hex", + "http-body 0.4.6", + "hyper 0.14.31", + "hyper-rustls 0.24.2", + "prost", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", + "tower", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.8", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.31", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "rustls 0.23.16", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper 0.14.31", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.5.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.5.0", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +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.87", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "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]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.1", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding 0.3.3", + "generic-array 0.14.7", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "libsqlite3-sys" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lightning-invoice" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ab9f6ea77e20e3129235e62a2e6bd64ed932363df104e864ee65ccffb54a8f" +dependencies = [ + "bech32 0.9.1", + "bitcoin", + "lightning-types", +] + +[[package]] +name = "lightning-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1083b8d9137000edf3bfcb1ff011c0d25e0cdd2feb98cc21d6765e64a494148f" +dependencies = [ + "bech32 0.9.1", + "bitcoin", + "hex-conservative 0.2.1", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + +[[package]] +name = "lnurl-rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41eacdd87b675792f7752f3dd0937a00241a504c3956c47f72986490662e1db4" +dependencies = [ + "aes", + "anyhow", + "base64 0.22.1", + "bech32 0.11.0", + "bitcoin", + "cbc", + "email_address", + "reqwest", + "serde", + "serde_json", + "ureq", + "url", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.1", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "md2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f130b74b5f0b05ffd405280ed1a9c2e4539fc3ca01f37b9ea947cd64922116e9" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + +[[package]] +name = "md4" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4030c65cf2aab7ada769cae7d1e7159f8d034d6ded4f39afba037f094bfd9a1" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "mostro" +version = "0.12.8" +dependencies = [ + "bitcoin", + "clap", + "config", + "easy-hasher", + "fedimint-tonic-lnd", + "lightning-invoice", + "lnurl-rs", + "mostro-core", + "nostr-sdk", + "once_cell", + "openssl", + "reqwest", + "serde", + "serde_json", + "sqlx", + "sqlx-crud", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", +] + +[[package]] +name = "mostro-core" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52433fda546a12791848792b51980953e66385ff733cbf42df687854315e8f5b" +dependencies = [ + "anyhow", + "bitcoin", + "bitcoin_hashes 0.15.0", + "chrono", + "nostr-sdk", + "serde", + "serde_json", + "sqlx", + "sqlx-crud", + "uuid", + "wasm-bindgen", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "negentropy" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" + +[[package]] +name = "negentropy" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a88da9dd148bbcdce323dd6ac47d369b4769d4a3b78c6c52389b9269f77932" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nostr" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aad4b767bbed24ac5eb4465bfb83bc1210522eb99d67cf4e547ec2ec7e47786" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bech32 0.11.0", + "bip39", + "bitcoin", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom", + "instant", + "negentropy 0.3.1", + "negentropy 0.4.3", + "once_cell", + "scrypt", + "serde", + "serde_json", + "unicode-normalization", + "url", +] + +[[package]] +name = "nostr-database" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23696338d51e45cd44e061823847f4b0d1d362eca80d5033facf9c184149f72f" +dependencies = [ + "async-trait", + "lru", + "nostr", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nostr-relay-pool" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15fcc6e3f0ca54d0fc779009bc5f2684cea9147be3b6aa68a7d301ea590f95f5" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "negentropy 0.3.1", + "negentropy 0.4.3", + "nostr", + "nostr-database", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "nostr-sdk" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "491221fc89b1aa189a0de640127127d68b4e7c5c1d44371b04d9a6d10694b5af" +dependencies = [ + "async-utility", + "atomic-destructor", + "nostr", + "nostr-database", + "nostr-relay-pool", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.4.0+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.7", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pest_meta" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.6.0", +] + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.1", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[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.87", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.87", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.0", + "hyper-rustls 0.27.3", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-socks", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.6.0", + "serde", + "serde_derive", +] + +[[package]] +name = "rust-ini" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.8", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2 0.10.8", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "indexmap 2.6.0", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +dependencies = [ + "ahash 0.7.8", + "atoi", + "bitflags 1.3.2", + "byteorder", + "bytes", + "chrono", + "crc 3.2.1", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "indexmap 1.9.3", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls 0.20.9", + "rustls-pemfile 1.0.4", + "serde", + "sha2 0.10.8", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "uuid", + "webpki-roots 0.22.6", +] + +[[package]] +name = "sqlx-crud" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00cbbfdea4be98477e9b5b7190b9e2b1e567e2c0b6c2649b6b6622cfffec50e" +dependencies = [ + "futures", + "sqlx", + "sqlx-crud-macros", + "thiserror", +] + +[[package]] +name = "sqlx-crud-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f8aaa082d86752ecd74230711220872649c2b3ef43186d1beb06a14fdf566fe" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "sqlx-core", + "sqlx-rt", + "syn 1.0.109", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.23.4", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot 0.12.3", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.16", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.16", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tungstenite", + "webpki-roots 0.26.6", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.7", + "bytes", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "tokio", + "tokio-rustls 0.24.1", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand", + "rustls 0.23.16", + "rustls-pki-types", + "sha1 0.10.6", + "thiserror", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3" +dependencies = [ + "base64 0.21.7", + "flate2", + "log", + "once_cell", + "rustls 0.21.12", + "rustls-webpki 0.101.7", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.25.4", +] + +[[package]] +name = "url" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", + "rand", + "serde", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b91f57fe13a38d0ce9e28a03463d8d3c2468ed03d75375110ec71d93b449a08" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "web-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[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 = "yaml-rust2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + +[[package]] +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.87", +] diff --git a/mostro/Cargo.toml b/mostro/Cargo.toml new file mode 100644 index 00000000..1f0d3d09 --- /dev/null +++ b/mostro/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "mostro" +version = "0.12.8" +edition = "2021" +license = "MIT" +authors = ["Francisco Calderón "] +description = "Lightning Network peer-to-peer nostr platform" +homepage = "https://mostro.network" +repository = "https://github.com/MostroP2P/mostro" + +[[bin]] +name = "mostrod" +path = "src/main.rs" + +[dependencies] +anyhow = { workspace = true } +chrono = { workspace = true } +easy-hasher = "2.2.1" +lightning-invoice = { workspace = true } +nostr-sdk = { workspace = true} +serde = { workspace = true } +serde_json = { workspace = true } +sqlx = { workspace = true } +sqlx-crud = { workspace = true } +tokio = { version = "1.42.0", features = ["full"] } +fedimint-tonic-lnd = "0.2.0" +uuid = { workspace = true } +reqwest = { version = "0.12.1", features = ["json"] } +mostro-core = { version = "0.6.21", features = ["sqlx"] } +tracing = "0.1.40" +tracing-subscriber = { workspace = true } +config = "0.14.0" +clap = { workspace = true } +lnurl-rs = "0.9.0" +openssl = { version = "0.10.66", features = ["vendored"] } +once_cell = "1.20.2" +bitcoin = "0.32.5" diff --git a/Cross.toml b/mostro/Cross.toml similarity index 100% rename from Cross.toml rename to mostro/Cross.toml diff --git a/INSTALL.md b/mostro/INSTALL.md similarity index 100% rename from INSTALL.md rename to mostro/INSTALL.md diff --git a/LICENSE b/mostro/LICENSE similarity index 100% rename from LICENSE rename to mostro/LICENSE diff --git a/Makefile b/mostro/Makefile similarity index 100% rename from Makefile rename to mostro/Makefile diff --git a/README.md b/mostro/README.md similarity index 100% rename from README.md rename to mostro/README.md diff --git a/mostro/archs b/mostro/archs new file mode 100644 index 00000000..6a0e542e --- /dev/null +++ b/mostro/archs @@ -0,0 +1,7 @@ +arm-unknown-linux-gnueabi +x86_64-unknown-linux-musl +aarch64-unknown-linux-musl +armv7-unknown-linux-gnueabi +x86_64-pc-windows-gnu +x86_64-unknown-freebsd +aarch64-linux-android diff --git a/build.rs b/mostro/build.rs similarity index 100% rename from build.rs rename to mostro/build.rs diff --git a/cross-compile.sh b/mostro/cross-compile.sh similarity index 100% rename from cross-compile.sh rename to mostro/cross-compile.sh diff --git a/docker/.env.example b/mostro/docker/.env.example similarity index 100% rename from docker/.env.example rename to mostro/docker/.env.example diff --git a/docker/Dockerfile b/mostro/docker/Dockerfile similarity index 100% rename from docker/Dockerfile rename to mostro/docker/Dockerfile diff --git a/docker/README.md b/mostro/docker/README.md similarity index 100% rename from docker/README.md rename to mostro/docker/README.md diff --git a/docker/compose.yml b/mostro/docker/compose.yml similarity index 100% rename from docker/compose.yml rename to mostro/docker/compose.yml diff --git a/docker/empty.mostro.db b/mostro/docker/empty.mostro.db similarity index 100% rename from docker/empty.mostro.db rename to mostro/docker/empty.mostro.db diff --git a/docker/relay_config.toml b/mostro/docker/relay_config.toml similarity index 100% rename from docker/relay_config.toml rename to mostro/docker/relay_config.toml diff --git a/docker/settings.docker.toml b/mostro/docker/settings.docker.toml similarity index 100% rename from docker/settings.docker.toml rename to mostro/docker/settings.docker.toml diff --git a/docker/start.sh b/mostro/docker/start.sh similarity index 100% rename from docker/start.sh rename to mostro/docker/start.sh diff --git a/init_db.sh b/mostro/init_db.sh similarity index 100% rename from init_db.sh rename to mostro/init_db.sh diff --git a/keys/negrunch.asc b/mostro/keys/negrunch.asc similarity index 100% rename from keys/negrunch.asc rename to mostro/keys/negrunch.asc diff --git a/migrations/20221222153301_orders.sql b/mostro/migrations/20221222153301_orders.sql similarity index 100% rename from migrations/20221222153301_orders.sql rename to mostro/migrations/20221222153301_orders.sql diff --git a/migrations/20230928145530_disputes.sql b/mostro/migrations/20230928145530_disputes.sql similarity index 100% rename from migrations/20230928145530_disputes.sql rename to mostro/migrations/20230928145530_disputes.sql diff --git a/migrations/20231005195154_users.sql b/mostro/migrations/20231005195154_users.sql similarity index 100% rename from migrations/20231005195154_users.sql rename to mostro/migrations/20231005195154_users.sql diff --git a/mostro/rust-toolchain.toml b/mostro/rust-toolchain.toml new file mode 100644 index 00000000..1173a45a --- /dev/null +++ b/mostro/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.82.0" +profile = "minimal" +components = ["clippy", "rust-docs", "rustfmt"] +targets = ["wasm32-unknown-unknown"] \ No newline at end of file diff --git a/settings.tpl.toml b/mostro/settings.tpl.toml similarity index 100% rename from settings.tpl.toml rename to mostro/settings.tpl.toml diff --git a/sqlx-data.json b/mostro/sqlx-data.json similarity index 100% rename from sqlx-data.json rename to mostro/sqlx-data.json diff --git a/src/app.rs b/mostro/src/app.rs similarity index 100% rename from src/app.rs rename to mostro/src/app.rs diff --git a/src/app/add_invoice.rs b/mostro/src/app/add_invoice.rs similarity index 100% rename from src/app/add_invoice.rs rename to mostro/src/app/add_invoice.rs diff --git a/src/app/admin_add_solver.rs b/mostro/src/app/admin_add_solver.rs similarity index 100% rename from src/app/admin_add_solver.rs rename to mostro/src/app/admin_add_solver.rs diff --git a/src/app/admin_cancel.rs b/mostro/src/app/admin_cancel.rs similarity index 100% rename from src/app/admin_cancel.rs rename to mostro/src/app/admin_cancel.rs diff --git a/src/app/admin_settle.rs b/mostro/src/app/admin_settle.rs similarity index 100% rename from src/app/admin_settle.rs rename to mostro/src/app/admin_settle.rs diff --git a/src/app/admin_take_dispute.rs b/mostro/src/app/admin_take_dispute.rs similarity index 100% rename from src/app/admin_take_dispute.rs rename to mostro/src/app/admin_take_dispute.rs diff --git a/src/app/cancel.rs b/mostro/src/app/cancel.rs similarity index 100% rename from src/app/cancel.rs rename to mostro/src/app/cancel.rs diff --git a/src/app/dispute.rs b/mostro/src/app/dispute.rs similarity index 100% rename from src/app/dispute.rs rename to mostro/src/app/dispute.rs diff --git a/src/app/fiat_sent.rs b/mostro/src/app/fiat_sent.rs similarity index 100% rename from src/app/fiat_sent.rs rename to mostro/src/app/fiat_sent.rs diff --git a/src/app/order.rs b/mostro/src/app/order.rs similarity index 100% rename from src/app/order.rs rename to mostro/src/app/order.rs diff --git a/src/app/rate_user.rs b/mostro/src/app/rate_user.rs similarity index 100% rename from src/app/rate_user.rs rename to mostro/src/app/rate_user.rs diff --git a/src/app/release.rs b/mostro/src/app/release.rs similarity index 100% rename from src/app/release.rs rename to mostro/src/app/release.rs diff --git a/src/app/take_buy.rs b/mostro/src/app/take_buy.rs similarity index 100% rename from src/app/take_buy.rs rename to mostro/src/app/take_buy.rs diff --git a/src/app/take_sell.rs b/mostro/src/app/take_sell.rs similarity index 100% rename from src/app/take_sell.rs rename to mostro/src/app/take_sell.rs diff --git a/src/bitcoin_price.rs b/mostro/src/bitcoin_price.rs similarity index 100% rename from src/bitcoin_price.rs rename to mostro/src/bitcoin_price.rs diff --git a/src/cli.rs b/mostro/src/cli.rs similarity index 100% rename from src/cli.rs rename to mostro/src/cli.rs diff --git a/src/cli/settings.rs b/mostro/src/cli/settings.rs similarity index 100% rename from src/cli/settings.rs rename to mostro/src/cli/settings.rs diff --git a/src/db.rs b/mostro/src/db.rs similarity index 100% rename from src/db.rs rename to mostro/src/db.rs diff --git a/src/error.rs b/mostro/src/error.rs similarity index 100% rename from src/error.rs rename to mostro/src/error.rs diff --git a/src/flow.rs b/mostro/src/flow.rs similarity index 100% rename from src/flow.rs rename to mostro/src/flow.rs diff --git a/src/lightning/invoice.rs b/mostro/src/lightning/invoice.rs similarity index 100% rename from src/lightning/invoice.rs rename to mostro/src/lightning/invoice.rs diff --git a/src/lightning/mod.rs b/mostro/src/lightning/mod.rs similarity index 100% rename from src/lightning/mod.rs rename to mostro/src/lightning/mod.rs diff --git a/src/lnurl.rs b/mostro/src/lnurl.rs similarity index 100% rename from src/lnurl.rs rename to mostro/src/lnurl.rs diff --git a/src/main.rs b/mostro/src/main.rs similarity index 100% rename from src/main.rs rename to mostro/src/main.rs diff --git a/src/messages.rs b/mostro/src/messages.rs similarity index 100% rename from src/messages.rs rename to mostro/src/messages.rs diff --git a/src/models.rs b/mostro/src/models.rs similarity index 100% rename from src/models.rs rename to mostro/src/models.rs diff --git a/src/nip33.rs b/mostro/src/nip33.rs similarity index 100% rename from src/nip33.rs rename to mostro/src/nip33.rs diff --git a/src/nip59.rs b/mostro/src/nip59.rs similarity index 100% rename from src/nip59.rs rename to mostro/src/nip59.rs diff --git a/src/scheduler.rs b/mostro/src/scheduler.rs similarity index 100% rename from src/scheduler.rs rename to mostro/src/scheduler.rs diff --git a/src/util.rs b/mostro/src/util.rs similarity index 100% rename from src/util.rs rename to mostro/src/util.rs diff --git a/mostro/static/logo.png b/mostro/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a69132dad4e154feec593a24b9dac0633132913b GIT binary patch literal 84471 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]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 Date: Sun, 29 Dec 2024 10:13:02 +0100 Subject: [PATCH 2/3] First working demo of mostro in workspace style with just as builder --- .cargo/config.toml | 2 + Cargo.lock | 60 +++++- Cargo.toml | 2 +- Justfile | 13 ++ .../20221222153301_orders.sql | 0 .../20230928145530_disputes.sql | 0 .../20231005195154_users.sql | 0 mostro-cli/Cargo.toml | 2 +- mostro-cli/src/cli/send_dm.rs | 1 - mostro-core/Cargo.toml | 3 +- mostro/Cargo.toml | 2 +- mostro/sqlx-data.json => sqlx-data.json | 0 xtask/Cargo.toml | 11 + xtask/src/main.rs | 190 ++++++++++++++++++ 14 files changed, 280 insertions(+), 6 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 Justfile rename {mostro/migrations => migrations}/20221222153301_orders.sql (100%) rename {mostro/migrations => migrations}/20230928145530_disputes.sql (100%) rename {mostro/migrations => migrations}/20231005195154_users.sql (100%) rename mostro/sqlx-data.json => sqlx-data.json (100%) create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..f0ccbc9a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 36ac7bdb..1f4d3335 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,38 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.9", +] + [[package]] name = "cbc" version = "0.1.2" @@ -1818,6 +1850,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "ihex" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" + [[package]] name = "indexmap" version = "1.9.3" @@ -2159,7 +2197,7 @@ dependencies = [ "lightning-invoice 0.32.0", "lnurl-rs", "mostro-core 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "nostr-sdk 0.37.0 (git+https://github.com/rust-nostr/nostr?rev=70db575d51965240aab1e1b3f1edab782c0ef625)", + "nostr-sdk 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell", "openssl", "reqwest", @@ -3254,6 +3292,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +dependencies = [ + "serde", +] + [[package]] name = "serde" version = "1.0.217" @@ -4679,6 +4726,17 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "cargo_metadata", + "clap", + "ihex", + "tracing", + "tracing-subscriber", +] + [[package]] name = "yaml-rust2" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index 04036772..f166c459 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,12 +6,12 @@ members = [ "mostro", "mostro-cli", "mostro-core", + "xtask", ] [workspace.dependencies] anyhow = "1.0.89" chrono = "0.4.35" -nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = ["nip06", "nip44", "nip59"], rev ="70db575d51965240aab1e1b3f1edab782c0ef625"} lightning-invoice = { version = "0.32.0", features = ["std"] } serde = { version = "1.0.210" } serde_json = "1.0.128" diff --git a/Justfile b/Justfile new file mode 100644 index 00000000..9e1ce1bb --- /dev/null +++ b/Justfile @@ -0,0 +1,13 @@ +# clean project +clean: + cargo xtask clean + +# build all the project with clean before +buildall: clean + cargo xtask build-all + +# build the project +build: + cargo xtask build + + diff --git a/mostro/migrations/20221222153301_orders.sql b/migrations/20221222153301_orders.sql similarity index 100% rename from mostro/migrations/20221222153301_orders.sql rename to migrations/20221222153301_orders.sql diff --git a/mostro/migrations/20230928145530_disputes.sql b/migrations/20230928145530_disputes.sql similarity index 100% rename from mostro/migrations/20230928145530_disputes.sql rename to migrations/20230928145530_disputes.sql diff --git a/mostro/migrations/20231005195154_users.sql b/migrations/20231005195154_users.sql similarity index 100% rename from mostro/migrations/20231005195154_users.sql rename to migrations/20231005195154_users.sql diff --git a/mostro-cli/Cargo.toml b/mostro-cli/Cargo.toml index 32f0edfc..e325afed 100644 --- a/mostro-cli/Cargo.toml +++ b/mostro-cli/Cargo.toml @@ -23,7 +23,7 @@ path = "src/main.rs" anyhow = { workspace = true } chrono = { workspace = true } clap = { workspace = true } -nostr-sdk = { workspace = true } +nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = ["nip06", "nip44", "nip59"], rev ="70db575d51965240aab1e1b3f1edab782c0ef625"} tokio = { version = "1.42.0", features = ["full"] } comfy-table = "7.0.1" log = "0.4.17" diff --git a/mostro-cli/src/cli/send_dm.rs b/mostro-cli/src/cli/send_dm.rs index 645e3040..3d646061 100644 --- a/mostro-cli/src/cli/send_dm.rs +++ b/mostro-cli/src/cli/send_dm.rs @@ -32,7 +32,6 @@ pub async fn execute_send_dm( std::process::exit(0) }; - send_message_sync(client, None, &trade_keys, receiver, message, true, true).await?; Ok(()) diff --git a/mostro-core/Cargo.toml b/mostro-core/Cargo.toml index a0d221d4..1fbceb55 100644 --- a/mostro-core/Cargo.toml +++ b/mostro-core/Cargo.toml @@ -20,7 +20,8 @@ sqlx-crud = { workspace = true, optional = true } wasm-bindgen = { version = "0.2.92", optional = true } bitcoin = "0.32.5" bitcoin_hashes = "0.15.0" -nostr-sdk = { workspace = true } +nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = ["nip06", "nip44", "nip59"], rev ="70db575d51965240aab1e1b3f1edab782c0ef625"} + [features] diff --git a/mostro/Cargo.toml b/mostro/Cargo.toml index 1f0d3d09..cac69190 100644 --- a/mostro/Cargo.toml +++ b/mostro/Cargo.toml @@ -17,7 +17,7 @@ anyhow = { workspace = true } chrono = { workspace = true } easy-hasher = "2.2.1" lightning-invoice = { workspace = true } -nostr-sdk = { workspace = true} +nostr-sdk = { version = "0.37.0", features = ["nip06", "nip44", "nip59"] } serde = { workspace = true } serde_json = { workspace = true } sqlx = { workspace = true } diff --git a/mostro/sqlx-data.json b/sqlx-data.json similarity index 100% rename from mostro/sqlx-data.json rename to sqlx-data.json diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 00000000..b3e24222 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +[dependencies] +cargo_metadata = "0.19.1" +clap = { workspace = true } +ihex = "3.0.0" +tracing = "0.1.40" +tracing-subscriber = { workspace = true } \ No newline at end of file diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 00000000..2584ef6e --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,190 @@ +use clap::{Parser, Subcommand}; +use std::env; +use std::path::{Path, PathBuf}; +use std::process::{exit, Command, Stdio}; +use tracing_subscriber::{fmt, prelude::*, EnvFilter}; + +#[derive(Parser)] +#[command(version, about, long_about = None)] +#[command(propagate_version = true)] +struct XtaskArgs { + #[command(subcommand)] + command: Commands, + #[arg(short, long)] + verbose: bool, +} + +// Commands enum +#[derive(Subcommand)] +enum Commands { + // Build all the project + #[command(verbatim_doc_comment)] + BuildAll, + // Build + #[command(verbatim_doc_comment)] + Build, + // Build db + #[command(verbatim_doc_comment)] + BuildDb, + #[command(verbatim_doc_comment)] + Clean, +} + +// Get the project root +fn project_root() -> PathBuf { + Path::new(&env!("CARGO_MANIFEST_DIR")) + .ancestors() + .nth(1) + .unwrap() + .to_path_buf() +} + +// Get the cargo command +pub fn cargo() -> String { + env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) +} + +// Clean the project +fn clean_project(verbose: bool) { + tracing::info!("Cleaning project...."); + let mut cargo_cmd = Command::new(cargo()); + let mut cmd = cargo_cmd.current_dir(project_root()).args(["clean"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running clean failed"); + if !status.success() { + tracing::error!("Failed to clean project"); + exit(-1); + } +} + +// Build the mostro db +fn build_mostro_db(verbose: bool) { + tracing::info!("Building mostro db...."); + env::set_var("DATABASE_URL", "sqlite://mostro.db"); + tracing::info!("DATABASE_URL: {}", env::var("DATABASE_URL").unwrap()); + + tracing::info!("Removing old database files"); + let mut cargo_cmd = Command::new("rm"); + let mut cmd = + cargo_cmd + .current_dir(project_root()) + .args(["-rf", "mostro.db*", "sqlx-data.json"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running rm failed"); + if !status.success() { + tracing::error!("Failed to remove old database files"); + exit(-1); + } + tracing::info!("Creating new database"); + let mut cargo_cmd = Command::new("sqlx"); + let mut cmd = cargo_cmd + .current_dir(project_root()) + .args(["database", "create"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running sqlx database create failed"); + if !status.success() { + tracing::error!("Failed to create database"); + exit(-1); + } + tracing::info!("Running migrations"); + let mut cargo_cmd = Command::new("sqlx"); + let mut cmd = cargo_cmd + .current_dir(project_root()) + .args(["migrate", "run"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running sqlx migrate run failed"); + if !status.success() { + tracing::error!("Failed to run migrations"); + exit(-1); + } + tracing::info!("Running sqlx prepare"); + let mut cargo_cmd = Command::new(cargo()); + let mut cmd = cargo_cmd + .current_dir(project_root()) + .args(["sqlx", "prepare", "--merged"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running sqlx prepare failed"); + if !status.success() { + tracing::error!("Failed to prepare database"); + exit(-1); + } + tracing::info!("Running sqlx prepare check"); + let mut cargo_cmd = Command::new(cargo()); + let mut cmd = cargo_cmd + .current_dir(project_root()) + .args(["sqlx", "prepare", "--check", "--merged"]); + if !verbose { + cmd = cmd.stdout(Stdio::null()).stderr(Stdio::null()); + } + let status = cmd.status().expect("Running sqlx prepare check failed"); + if !status.success() { + tracing::error!("Failed to prepare database"); + exit(-1); + } + tracing::info!("Mostro db created successfully"); +} + +fn build_all(verbose: bool) { + tracing::info!("Building all...."); + let mut cargo_cmd = Command::new(cargo()); + let mut cmd = cargo_cmd + .current_dir(project_root()) + .args(["build", "--release"]); + if !verbose { + cmd = cmd + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .arg("--quiet"); + } + let status = cmd.status().expect("Running Cargo failed"); + if !status.success() { + tracing::error!("All Mostro crates build failed"); + exit(-1); + } + tracing::info!("All Mostro crates build successfully!"); +} + +// Main function +fn main() { + // Adding some info tracing just for logging activity + env::set_var("RUST_LOG", "info"); + + // Tracing using RUST_LOG + tracing_subscriber::registry() + .with(fmt::layer()) + .with(EnvFilter::from_default_env()) + .init(); + + let args = XtaskArgs::parse(); + + match args.command { + // Build all the project + Commands::BuildAll => { + clean_project(args.verbose); + build_mostro_db(args.verbose); + build_all(args.verbose); + } + // Build the project + Commands::Build => { + build_all(args.verbose); + } + // Build the mostro db + Commands::BuildDb => { + build_mostro_db(args.verbose); + } + // Clean the project + Commands::Clean => { + clean_project(args.verbose); + } + } +} From 279219885fbd880cffe023291b1a0699831ada6c Mon Sep 17 00:00:00 2001 From: arkanoider Date: Sun, 29 Dec 2024 10:32:40 +0100 Subject: [PATCH 3/3] Add of runner commands --- Justfile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 9e1ce1bb..6fa2d1a4 100644 --- a/Justfile +++ b/Justfile @@ -3,11 +3,22 @@ clean: cargo xtask clean # build all the project with clean before -buildall: clean +build-all: clean cargo xtask build-all # build the project build: cargo xtask build +# build the mostro db +build-db: + cargo xtask build-db + +# run mostro +run-mostro: + cargo run --release --bin mostrod + +# run mostro debug +runmostro-debug: + cargo run --bin mostrod