From 59b7c95d0fe75b8a8daf6145a84120daaecfb123 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 17 Oct 2025 19:05:06 +0200 Subject: [PATCH 1/5] glclient: Fix a deprecation and a panic --- libs/gl-client/CHANGELOG.md | 2 ++ libs/gl-client/src/utils.rs | 24 +++++++++++++++++++----- libs/gl-testing/gltesting/identity.py | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libs/gl-client/CHANGELOG.md b/libs/gl-client/CHANGELOG.md index c291cd5ed..4a60e6d30 100644 --- a/libs/gl-client/CHANGELOG.md +++ b/libs/gl-client/CHANGELOG.md @@ -9,3 +9,5 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed - Addressed an issue with signers being unable to connect to the node, due to an SNI header override that is no longer required +- Parsing an invalid certificate no longer panics, instead returning an error. +- Addressed a deprecation warning in gl-testing regarding PROTOCOL_TLS being renamed to PROTOCOL_TLS_SERVER diff --git a/libs/gl-client/src/utils.rs b/libs/gl-client/src/utils.rs index 7795938c1..40883cc14 100644 --- a/libs/gl-client/src/utils.rs +++ b/libs/gl-client/src/utils.rs @@ -1,5 +1,5 @@ -use anyhow::{anyhow, Result}; use crate::tls::TlsConfig; +use anyhow::{anyhow, Result}; pub fn scheduler_uri() -> String { std::env::var("GL_SCHEDULER_GRPC_URI") @@ -25,7 +25,21 @@ pub fn get_node_id_from_tls_config(tls_config: &TlsConfig) -> Result> { let split_subject_common_name = subject_common_name.split("/").collect::>(); - assert!(split_subject_common_name[1] == "users"); - Ok(hex::decode(split_subject_common_name[2]) - .expect("Failed to parse the node_id from the TlsConfig to bytes")) -} \ No newline at end of file + // Must have at least 3 components: "" / "users" / "node_id" + if split_subject_common_name.len() < 3 { + return Err(anyhow!( + "Could not parse subject common name: {}", + subject_common_name + )); + } else if (split_subject_common_name[1] != "users") { + return Err(anyhow!("Not a users certificate: {}", subject_common_name)); + } + + hex::decode(split_subject_common_name[2]).map_err(|e| { + anyhow!( + "Unable to decode node_id ({}): {}", + split_subject_common_name[2], + e + ) + }) +} diff --git a/libs/gl-testing/gltesting/identity.py b/libs/gl-testing/gltesting/identity.py index 9cd583269..bb63e3539 100644 --- a/libs/gl-testing/gltesting/identity.py +++ b/libs/gl-testing/gltesting/identity.py @@ -55,7 +55,7 @@ def to_server_credentials(self): ) def to_ssl_context(self): - s = ssl.SSLContext(ssl.PROTOCOL_TLS) + s = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) s.load_cert_chain(self.cert_chain_path, keyfile=self.private_key_path) s.load_verify_locations(capath=self.caroot_path) s.set_alpn_protocols(['h2']) From 469f85848e56e03c9a56284cceb44a25124fc142 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 17 Oct 2025 19:10:03 +0200 Subject: [PATCH 2/5] glsdk: Initial attempt to get bindings working via uniffi --- Cargo.lock | 1222 +++++++++++------- Cargo.toml | 2 + Taskfile.yml | 4 + libs/gl-client/.kacl.yml | 52 + libs/gl-sdk/.tasks.yml | 112 ++ libs/gl-sdk/CLAUDE.md | 85 ++ libs/gl-sdk/Cargo.toml | 19 + libs/gl-sdk/README.md | 83 ++ libs/gl-sdk/glsdk/__init__.py | 9 + libs/gl-sdk/glsdk/glsdk.py | 1687 +++++++++++++++++++++++++ libs/gl-sdk/pyproject.toml | 39 + libs/gl-sdk/src/credentials.rs | 22 + libs/gl-sdk/src/lib.rs | 46 + libs/gl-sdk/src/node.rs | 26 + libs/gl-sdk/src/scheduler.rs | 61 + libs/gl-sdk/src/signer.rs | 90 ++ libs/gl-sdk/src/util.rs | 21 + libs/gl-sdk/tests/test_basic.py | 68 + libs/gl-sdk/tests/test_credentials.py | 129 ++ libs/gl-sdk/tests/test_scheduler.py | 10 + libs/uniffi-bindgen/Cargo.toml | 12 + libs/uniffi-bindgen/src/main.rs | 3 + pyproject.toml | 1 + 23 files changed, 3357 insertions(+), 446 deletions(-) create mode 100644 libs/gl-client/.kacl.yml create mode 100644 libs/gl-sdk/.tasks.yml create mode 100644 libs/gl-sdk/CLAUDE.md create mode 100644 libs/gl-sdk/Cargo.toml create mode 100644 libs/gl-sdk/README.md create mode 100644 libs/gl-sdk/glsdk/__init__.py create mode 100644 libs/gl-sdk/glsdk/glsdk.py create mode 100644 libs/gl-sdk/pyproject.toml create mode 100644 libs/gl-sdk/src/credentials.rs create mode 100644 libs/gl-sdk/src/lib.rs create mode 100644 libs/gl-sdk/src/node.rs create mode 100644 libs/gl-sdk/src/scheduler.rs create mode 100644 libs/gl-sdk/src/signer.rs create mode 100644 libs/gl-sdk/src/util.rs create mode 100644 libs/gl-sdk/tests/test_basic.py create mode 100644 libs/gl-sdk/tests/test_credentials.py create mode 100644 libs/gl-sdk/tests/test_scheduler.py create mode 100644 libs/uniffi-bindgen/Cargo.toml create mode 100644 libs/uniffi-bindgen/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index db41030ee..2a214c522 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -76,19 +76,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] -[[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" @@ -100,9 +94,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -115,9 +109,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -130,29 +124,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "as-any" @@ -160,6 +154,48 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" +[[package]] +name = "askama" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn 2.0.110", +] + +[[package]] +name = "askama_parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + [[package]] name = "asn1-rs" version = "0.5.2" @@ -218,18 +254,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -296,9 +332,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -306,7 +342,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -333,11 +369,20 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + [[package]] name = "bcder" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ffdaa8c6398acd07176317eb6c1f9082869dd1cc3fee7c72c6354866b928cc" +checksum = "1f7c42c9913f68cf9390a225e81ad56a5c515347287eb98baa710090ca1de86d" dependencies = [ "bytes", "smallvec", @@ -479,9 +524,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -533,27 +578,60 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" dependencies = [ "serde", ] +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.17", +] + [[package]] name = "cc" -version = "1.2.29" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -587,11 +665,10 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", @@ -628,9 +705,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.41" +version = "4.5.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" +checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8" dependencies = [ "clap_builder", "clap_derive", @@ -638,9 +715,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.41" +version = "4.5.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" +checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1" dependencies = [ "anstream", "anstyle", @@ -650,21 +727,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clightningrpc" @@ -816,9 +893,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core", @@ -836,9 +913,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", @@ -846,27 +923,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -901,9 +978,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -951,7 +1028,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -962,7 +1039,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -988,9 +1065,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -1016,7 +1093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", - "humantime 2.2.0", + "humantime 2.3.0", "log", "regex", "termcolor", @@ -1028,7 +1105,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ - "humantime 2.2.0", + "humantime 2.3.0", "is-terminal", "log", "regex", @@ -1056,12 +1133,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1072,16 +1149,22 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1105,9 +1188,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1118,6 +1201,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + [[package]] name = "fs2" version = "0.4.3" @@ -1184,7 +1276,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1250,19 +1342,19 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] [[package]] @@ -1277,9 +1369,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "gl-cli" @@ -1291,7 +1383,7 @@ dependencies = [ "futures", "gl-client", "hex", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "vls-core", ] @@ -1418,6 +1510,18 @@ dependencies = [ "vls-protocol", ] +[[package]] +name = "gl-sdk" +version = "0.1.0" +dependencies = [ + "bip39", + "gl-client", + "once_cell", + "thiserror 2.0.17", + "tokio", + "uniffi", +] + [[package]] name = "gl-signerproxy" version = "0.3.1" @@ -1446,6 +1550,23 @@ dependencies = [ "tonic 0.11.0", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "goblin" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" +dependencies = [ + "log", + "plain", + "scroll", +] + [[package]] name = "governor" version = "0.5.1" @@ -1457,7 +1578,7 @@ dependencies = [ "futures-timer", "no-std-compat", "nonzero_ext", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "smallvec", ] @@ -1473,7 +1594,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.10.0", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -1497,9 +1618,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "heck" @@ -1548,11 +1669,11 @@ checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1600,9 +1721,9 @@ dependencies = [ [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" @@ -1621,7 +1742,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -1656,9 +1777,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1680,9 +1801,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1693,9 +1814,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1706,11 +1827,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1721,42 +1841,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1772,9 +1888,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1803,12 +1919,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", ] [[package]] @@ -1855,17 +1971,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -1874,20 +1979,20 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -1915,33 +2020,33 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1987,9 +2092,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" @@ -1999,13 +2104,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.4" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "libc", - "redox_syscall 0.5.13", + "redox_syscall 0.5.18", ] [[package]] @@ -2051,39 +2156,38 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -2094,9 +2198,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -2136,19 +2240,19 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -2196,7 +2300,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -2249,12 +2353,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -2323,9 +2426,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -2356,9 +2459,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opaque-debug" @@ -2378,12 +2481,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[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" @@ -2397,12 +2494,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core 0.9.11", + "parking_lot_core 0.9.12", ] [[package]] @@ -2421,15 +2518,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.13", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2454,19 +2551,19 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" @@ -2475,7 +2572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.10.0", + "indexmap 2.12.0", ] [[package]] @@ -2613,7 +2710,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2628,6 +2725,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "poly1305" version = "0.8.0" @@ -2668,9 +2771,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -2732,19 +2835,19 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -2804,11 +2907,11 @@ dependencies = [ "multimap 0.10.1", "once_cell", "petgraph", - "prettyplease 0.2.35", + "prettyplease 0.2.37", "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.104", + "syn 2.0.110", "tempfile", ] @@ -2835,7 +2938,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2866,7 +2969,7 @@ dependencies = [ "indoc", "libc", "memoffset", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", @@ -2925,9 +3028,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2992,67 +3095,52 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "regex-automata", + "regex-syntax", ] [[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.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[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" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" @@ -3155,16 +3243,22 @@ dependencies = [ "crypto", "env_logger 0.10.2", "hex", - "indexmap 2.10.0", + "indexmap 2.12.0", "sha2 0.10.9", "thiserror 1.0.69", ] [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rusticata-macros" @@ -3181,7 +3275,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3190,15 +3284,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -3271,9 +3365,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "zeroize", ] @@ -3301,9 +3395,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -3322,11 +3416,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3335,6 +3429,26 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scroll" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "sct" version = "0.7.1" @@ -3401,7 +3515,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "core-foundation", "core-foundation-sys", "libc", @@ -3410,20 +3524,31 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -3441,34 +3566,45 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -3485,15 +3621,14 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "10574371d41b0d9b2cff89418eda27da52bcaff2cc8741db26382a77c29131f1" dependencies = [ "base64 0.22.1", "chrono", "hex", - "serde", - "serde_derive", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -3501,14 +3636,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +checksum = "08a72d8216842fdd57820dc78d840bef99248e35fb2554ff923319e60f2d686b" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3590,9 +3725,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -3618,11 +3753,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "sled" @@ -3646,6 +3787,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "socket2" version = "0.5.10" @@ -3656,6 +3803,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "spin" version = "0.5.2" @@ -3680,9 +3837,15 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" @@ -3709,9 +3872,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -3744,7 +3907,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3776,15 +3939,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", - "rustix 1.0.8", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -3802,6 +3965,15 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -3813,11 +3985,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -3828,18 +4000,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3853,9 +4025,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -3868,15 +4040,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -3884,9 +4056,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -3894,9 +4066,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -3909,29 +4081,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.46.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", - "mio 1.0.4", - "parking_lot 0.12.4", + "mio 1.1.0", + "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-io-timeout" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" dependencies = [ "pin-project-lite", "tokio", @@ -3939,13 +4108,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3994,9 +4163,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -4005,6 +4174,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tonic" version = "0.8.3" @@ -4088,11 +4266,11 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" dependencies = [ - "prettyplease 0.2.35", + "prettyplease 0.2.37", "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -4147,7 +4325,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -4183,14 +4361,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -4219,21 +4397,21 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] @@ -4244,6 +4422,146 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "uniffi" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3291800a6b06569f7d3e15bdb6dc235e0f0c8bd3eb07177f430057feb076415f" +dependencies = [ + "anyhow", + "camino", + "cargo_metadata", + "clap", + "uniffi_bindgen", + "uniffi_build", + "uniffi_core", + "uniffi_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi-bindgen" +version = "0.1.0" +dependencies = [ + "uniffi", +] + +[[package]] +name = "uniffi_bindgen" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a04b99fa7796eaaa7b87976a0dbdd1178dc1ee702ea00aca2642003aef9b669e" +dependencies = [ + "anyhow", + "askama", + "camino", + "cargo_metadata", + "fs-err", + "glob", + "goblin", + "heck 0.5.0", + "indexmap 2.12.0", + "once_cell", + "serde", + "tempfile", + "textwrap", + "toml", + "uniffi_internal_macros", + "uniffi_meta", + "uniffi_pipeline", + "uniffi_udl", +] + +[[package]] +name = "uniffi_build" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "025a05cba02ee22b6624ac3d257e59c7395319ea8fe1aae33a7cdb4e2a3016cc" +dependencies = [ + "anyhow", + "camino", + "uniffi_bindgen", +] + +[[package]] +name = "uniffi_core" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38a9a27529ccff732f8efddb831b65b1e07f7dea3fd4cacd4a35a8c4b253b98" +dependencies = [ + "anyhow", + "bytes", + "once_cell", + "static_assertions", +] + +[[package]] +name = "uniffi_internal_macros" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09acd2ce09c777dd65ee97c251d33c8a972afc04873f1e3b21eb3492ade16933" +dependencies = [ + "anyhow", + "indexmap 2.12.0", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "uniffi_macros" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5596f178c4f7aafa1a501c4e0b96236a96bc2ef92bdb453d83e609dad0040152" +dependencies = [ + "camino", + "fs-err", + "once_cell", + "proc-macro2", + "quote", + "serde", + "syn 2.0.110", + "toml", + "uniffi_meta", +] + +[[package]] +name = "uniffi_meta" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beadc1f460eb2e209263c49c4f5b19e9a02e00a3b2b393f78ad10d766346ecff" +dependencies = [ + "anyhow", + "siphasher", + "uniffi_internal_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_pipeline" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd76b3ac8a2d964ca9fce7df21c755afb4c77b054a85ad7a029ad179cc5abb8a" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.12.0", + "tempfile", + "uniffi_internal_macros", +] + +[[package]] +name = "uniffi_udl" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319cf905911d70d5b97ce0f46f101619a22e9a189c8c46d797a9955e9233716" +dependencies = [ + "anyhow", + "textwrap", + "uniffi_meta", + "weedle2", +] + [[package]] name = "unindent" version = "0.1.11" @@ -4284,13 +4602,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4307,9 +4626,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "js-sys", "serde", @@ -4449,45 +4768,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -4498,9 +4804,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4508,31 +4814,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.104", - "wasm-bindgen-backend", + "syn 2.0.110", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -4548,6 +4854,15 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "weedle2" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" +dependencies = [ + "nom", +] + [[package]] name = "which" version = "4.4.2" @@ -4578,11 +4893,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4593,9 +4908,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -4606,46 +4921,46 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "windows-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] @@ -4683,7 +4998,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -4719,18 +5043,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -4747,9 +5072,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -4765,9 +5090,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -4783,9 +5108,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -4795,9 +5120,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -4813,9 +5138,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -4831,9 +5156,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -4849,9 +5174,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -4867,9 +5192,18 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -4882,19 +5216,16 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x509-certificate" @@ -4907,7 +5238,7 @@ dependencies = [ "chrono", "der", "hex", - "pem 3.0.5", + "pem 3.0.6", "ring 0.17.14", "signature", "spki", @@ -4945,11 +5276,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -4957,34 +5287,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", "synstructure 0.13.2", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -5004,15 +5334,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", "synstructure 0.13.2", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] @@ -5025,14 +5355,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -5041,9 +5371,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -5052,11 +5382,11 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] diff --git a/Cargo.toml b/Cargo.toml index defb1487f..daba37308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,8 @@ members = [ "libs/gl-signerproxy", "libs/gl-cli", "libs/gl-util", + "libs/gl-sdk", + "libs/uniffi-bindgen", ] [workspace.dependencies] diff --git a/Taskfile.yml b/Taskfile.yml index e028444af..d923319ad 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -25,6 +25,10 @@ includes: taskfile: "libs/gl-signerproxy/.tasks.yml" dir: "." + sdk: + taskfile: "libs/gl-sdk/.tasks.yml" + dir: "." + tasks: ci-check: deps: diff --git a/libs/gl-client/.kacl.yml b/libs/gl-client/.kacl.yml new file mode 100644 index 000000000..6ce4f7a36 --- /dev/null +++ b/libs/gl-client/.kacl.yml @@ -0,0 +1,52 @@ +kacl: + file: CHANGELOG.md + allowed_header_titles: + - Changelog + - Change Log + allowed_version_sections: + - Added + - Changed + - Deprecated + - Removed + - Fixed + - Security + default_content: + - All notable changes to this project will be documented in this file. + - The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + release: + add_unreleased: True + git: + commit: False + commit_message: "[skip ci] Releasing Changelog version {new_version}" + commit_additional_files: [] + tag: False + tag_name: "v{new_version}" + tag_description: "Version v{new_version} released" + links: + auto_generate: False + compare_versions_template: '{host}/compare/{previous_version}...{version}' + unreleased_changes_template: '{host}/compare/{latest_version}...master' + initial_version_template: '{host}/tree/{version}' + extension: + post_release_version_prefix: null + issue_tracker: + jira: + host: null + username: null + password: null + issue_patterns: ["[A-Z]+-[0-9]+"] + comment_template: | + # 🚀 New version [v{new_version}]({link}) + + A new release has been created referencing this issue. Please check it out. + + ## 🚧 Changes in this version + + {changes} + + ## 🧭 Reference + + Code: [Source Code Management System]({link}) + stash: + directory: .kacl_stash + always: False diff --git a/libs/gl-sdk/.tasks.yml b/libs/gl-sdk/.tasks.yml new file mode 100644 index 000000000..49a614759 --- /dev/null +++ b/libs/gl-sdk/.tasks.yml @@ -0,0 +1,112 @@ +version: "3" + +tasks: + build: + desc: "Build the gl-sdk library" + dir: "{{.ROOT_DIR}}" + cmds: + - cargo build -p gl-sdk + + build-release: + desc: "Build the gl-sdk library in release mode" + dir: "{{.ROOT_DIR}}" + cmds: + - cargo build -p gl-sdk --release + + bindings-python: + desc: "Generate Python bindings" + dir: "{{.ROOT_DIR}}" + deps: + - build-release + cmds: + - | + cargo run --bin uniffi-bindgen -- generate \ + --library ${CARGO_TARGET_DIR:-target}/release/libglsdk.so \ + --language python \ + --out-dir ./libs/gl-sdk/bindings + + bindings-kotlin: + desc: "Generate Kotlin bindings" + dir: "{{.ROOT_DIR}}" + deps: + - build-release + cmds: + - | + cargo run --bin uniffi-bindgen -- generate \ + --library ${CARGO_TARGET_DIR:-target}/release/libglsdk.so \ + --language kotlin \ + --out-dir ./libs/gl-sdk/bindings + + bindings-swift: + desc: "Generate Swift bindings" + dir: "{{.ROOT_DIR}}" + deps: + - build-release + cmds: + - | + cargo run --bin uniffi-bindgen -- generate \ + --library ${CARGO_TARGET_DIR:-target}/release/libglsdk.so \ + --language swift \ + --out-dir ./libs/gl-sdk/bindings + + bindings-ruby: + desc: "Generate Ruby bindings" + dir: "{{.ROOT_DIR}}" + deps: + - build-release + cmds: + - | + cargo run --bin uniffi-bindgen -- generate \ + --library ${CARGO_TARGET_DIR:-target}/release/libglsdk.so \ + --language ruby \ + --out-dir ./libs/gl-sdk/bindings + + bindings-all: + desc: "Generate all language bindings" + dir: "{{.ROOT_DIR}}" + deps: + - bindings-python + - bindings-kotlin + - bindings-swift + - bindings-ruby + + package-python: + desc: "Build Python wheel package" + dir: "{{.ROOT_DIR}}/libs/gl-sdk" + cmds: + - task: build-release + - task: bindings-python + - uv run python build.py + - uv build + + install-python: + desc: "Install Python package in development mode" + dir: "{{.ROOT_DIR}}/libs/gl-sdk" + cmds: + - task: package-python + - uv pip install -e . + + prepare-test: + desc: "Prepare test environment by copying bindings to package" + dir: "{{.ROOT_DIR}}/libs/gl-sdk" + cmds: + - task: bindings-python + - uv run python build.py + + test: + desc: "Run gl-sdk tests (loads library from source)" + dir: "{{.ROOT_DIR}}/libs/gl-sdk" + deps: + - prepare-test + cmds: + - uv run pytest tests -v + + clean: + desc: "Clean generated bindings and build artifacts" + dir: "{{.ROOT_DIR}}/libs/gl-sdk" + cmds: + - rm -rf ./bindings + - rm -rf dist/ build/ *.egg-info + - rm -f glsdk/*.so glsdk/glsdk.py + - find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true + - find . -type f -name "*.pyc" -delete diff --git a/libs/gl-sdk/CLAUDE.md b/libs/gl-sdk/CLAUDE.md new file mode 100644 index 000000000..eeff2b703 --- /dev/null +++ b/libs/gl-sdk/CLAUDE.md @@ -0,0 +1,85 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +`gl-sdk` is a Rust library that provides UniFFI-based language bindings for the Greenlight Lightning Network client. It wraps the core `gl-client` library and generates bindings for Python, Kotlin, Swift, and Ruby using Mozilla's UniFFI framework. + +**Key Architecture:** +- Core Rust library (`src/lib.rs`) wraps `gl-client` types with UniFFI-compatible interfaces +- UniFFI generates foreign language bindings from the Rust implementation +- Main types: `Credentials`, `Node`, and `Signer` (all currently under development) +- Dependencies: Built on top of `gl-client` (v0.3.1) which handles the actual Greenlight protocol + +## Building and Testing + +**Build the library:** +```bash +# From workspace root or any directory +task sdk:build + +# Or directly with cargo from workspace root +cargo build -p gl-sdk +``` + +**Build for release:** +```bash +task sdk:build-release +``` + +**Run tests:** +```bash +# From workspace root +cargo test -p gl-sdk + +# Run specific test +cargo test -p gl-sdk +``` + +Note: Currently there are no tests in the `tests/` directory. + +## Generating Language Bindings + +UniFFI bindings must be generated after building the library. The build must complete first to produce the shared library that uniffi-bindgen processes. + +**Generate all bindings:** +```bash +task sdk:bindings-all +``` + +**Generate specific language:** +```bash +task sdk:bindings-python # Python +task sdk:bindings-kotlin # Kotlin +task sdk:bindings-swift # Swift +task sdk:bindings-ruby # Ruby +``` + +**Clean generated bindings:** +```bash +task sdk:clean +``` + +All bindings are generated into `bindings/` directory. + +## Important Notes + +- **Workspace structure:** This is a workspace member. The workspace root is at `/home/cdecker/dev/greenlight/202509-sdk/public/` +- **Task commands:** All `task sdk:*` commands work from any directory in the workspace +- **UniFFI workflow:** Build library first, then generate bindings. UniFFI reads the compiled library to generate foreign code. +- **Working directory:** When using cargo directly, commands should be run from the workspace root with `-p gl-sdk` +- **Current state:** Most functionality is unimplemented (marked with `unimplemented!()` or `todo!()`). The library is in early development. + +## Related Libraries + +- `gl-client`: Core Greenlight client library that this SDK wraps +- `uniffi-bindgen`: Custom workspace binary for generating language bindings +- `gl-testing`: Testing utilities (available as dev dependency via uv) + +## Development with Python + +Python bindings and testing use `uv` for dependency management: +- Use `uv run python3` instead of `python` or `python3` +- Python version: 3.10+ (specified in `.python-version`) +- Dev dependency: `gl-testing` for integration tests diff --git a/libs/gl-sdk/Cargo.toml b/libs/gl-sdk/Cargo.toml new file mode 100644 index 000000000..dd9b14079 --- /dev/null +++ b/libs/gl-sdk/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "gl-sdk" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["cdylib", "staticlib"] +name = "glsdk" + +[dependencies] +bip39 = "2.2.0" +gl-client = { version = "0.3.1", path = "../gl-client" } +once_cell = "1.21.3" +thiserror = "2.0.17" +tokio = { version = "1", features = ["sync"] } +uniffi = { version = "0.29.4" } + +[build-dependencies] +uniffi = { version = "0.29.4", features = [ "build" ] } diff --git a/libs/gl-sdk/README.md b/libs/gl-sdk/README.md new file mode 100644 index 000000000..37c35383b --- /dev/null +++ b/libs/gl-sdk/README.md @@ -0,0 +1,83 @@ +# gl-sdk + +Rust SDK for Greenlight with UniFFI bindings support. + +## Building + +Build the library using Task: + +```bash +task sdk:build +``` + +Or directly with cargo from the workspace root: + +```bash +cd /home/cdecker/dev/greenlight/202509-sdk/public +cargo build -p gl-sdk +``` + +## Generating Language Bindings + +### Using Task (Recommended) + +The easiest way to generate bindings is using the Task commands: + +```bash +# Generate Python bindings +task sdk:bindings-python + +# Generate Kotlin bindings +task sdk:bindings-kotlin + +# Generate Swift bindings +task sdk:bindings-swift + +# Generate Ruby bindings +task sdk:bindings-ruby + +# Generate all language bindings +task sdk:bindings-all +``` + +These commands work from any directory in the workspace. + +### Using uniffi-bindgen Directly + +The project uses [UniFFI](https://mozilla.github.io/uniffi-rs/) to generate bindings for multiple languages from the UDL definition in `src/sdk.udl`. + +The `uniffi-bindgen` tool is included in the workspace at `libs/uniffi-bindgen`. + +**Note:** When using uniffi-bindgen directly, all commands must be run from the workspace root. + +#### Generate Python Bindings + +```bash +cd /home/cdecker/dev/greenlight/202509-sdk/public +cargo run --bin uniffi-bindgen -- generate \ + --library $CARGO_TARGET_DIR/debug/libglsdk.so \ + --language python \ + --out-dir ./libs/gl-sdk/bindings +``` + +#### Generate Bindings for Other Languages + +Replace `--language python` with: +- `kotlin` for Kotlin +- `swift` for Swift +- `ruby` for Ruby + +Example for Kotlin: + +```bash +cargo run --bin uniffi-bindgen -- generate \ + --library $CARGO_TARGET_DIR/debug/libglsdk.so \ + --language kotlin \ + --out-dir ./libs/gl-sdk/bindings +``` + +## Files + +- `src/sdk.udl` - UniFFI interface definition +- `build.rs` - Build script that generates Rust scaffolding +- `bindings/` - Generated language bindings (created by uniffi-bindgen) diff --git a/libs/gl-sdk/glsdk/__init__.py b/libs/gl-sdk/glsdk/__init__.py new file mode 100644 index 000000000..744eb5c63 --- /dev/null +++ b/libs/gl-sdk/glsdk/__init__.py @@ -0,0 +1,9 @@ +"""Greenlight SDK - UniFFI Python bindings for Greenlight. + +This package provides Python bindings to the Greenlight Lightning Network +client library, generated using Mozilla's UniFFI framework. +""" + +from .glsdk import * # noqa: F401, F403 + +__version__ = "0.1.0" diff --git a/libs/gl-sdk/glsdk/glsdk.py b/libs/gl-sdk/glsdk/glsdk.py new file mode 100644 index 000000000..78a9bef28 --- /dev/null +++ b/libs/gl-sdk/glsdk/glsdk.py @@ -0,0 +1,1687 @@ + + +# This file was autogenerated by some hot garbage in the `uniffi` crate. +# Trust me, you don't want to mess with it! + +# Common helper code. +# +# Ideally this would live in a separate .py file where it can be unittested etc +# in isolation, and perhaps even published as a re-useable package. +# +# However, it's important that the details of how this helper code works (e.g. the +# way that different builtin types are passed across the FFI) exactly match what's +# expected by the rust code on the other side of the interface. In practice right +# now that means coming from the exact some version of `uniffi` that was used to +# compile the rust component. The easiest way to ensure this is to bundle the Python +# helpers directly inline like we're doing here. + +from __future__ import annotations +import os +import sys +import ctypes +import enum +import struct +import contextlib +import datetime +import threading +import itertools +import traceback +import typing +import platform + +# Used for default argument values +_DEFAULT = object() # type: typing.Any + + +class _UniffiRustBuffer(ctypes.Structure): + _fields_ = [ + ("capacity", ctypes.c_uint64), + ("len", ctypes.c_uint64), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + @staticmethod + def default(): + return _UniffiRustBuffer(0, 0, None) + + @staticmethod + def alloc(size): + return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_alloc, size) + + @staticmethod + def reserve(rbuf, additional): + return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_reserve, rbuf, additional) + + def free(self): + return _uniffi_rust_call(_UniffiLib.ffi_glsdk_rustbuffer_free, self) + + def __str__(self): + return "_UniffiRustBuffer(capacity={}, len={}, data={})".format( + self.capacity, + self.len, + self.data[0:self.len] + ) + + @contextlib.contextmanager + def alloc_with_builder(*args): + """Context-manger to allocate a buffer using a _UniffiRustBufferBuilder. + + The allocated buffer will be automatically freed if an error occurs, ensuring that + we don't accidentally leak it. + """ + builder = _UniffiRustBufferBuilder() + try: + yield builder + except: + builder.discard() + raise + + @contextlib.contextmanager + def consume_with_stream(self): + """Context-manager to consume a buffer using a _UniffiRustBufferStream. + + The _UniffiRustBuffer will be freed once the context-manager exits, ensuring that we don't + leak it even if an error occurs. + """ + try: + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError("junk data left in buffer at end of consume_with_stream") + finally: + self.free() + + @contextlib.contextmanager + def read_with_stream(self): + """Context-manager to read a buffer using a _UniffiRustBufferStream. + + This is like consume_with_stream, but doesn't free the buffer afterwards. + It should only be used with borrowed `_UniffiRustBuffer` data. + """ + s = _UniffiRustBufferStream.from_rust_buffer(self) + yield s + if s.remaining() != 0: + raise RuntimeError("junk data left in buffer at end of read_with_stream") + +class _UniffiForeignBytes(ctypes.Structure): + _fields_ = [ + ("len", ctypes.c_int32), + ("data", ctypes.POINTER(ctypes.c_char)), + ] + + def __str__(self): + return "_UniffiForeignBytes(len={}, data={})".format(self.len, self.data[0:self.len]) + + +class _UniffiRustBufferStream: + """ + Helper for structured reading of bytes from a _UniffiRustBuffer + """ + + def __init__(self, data, len): + self.data = data + self.len = len + self.offset = 0 + + @classmethod + def from_rust_buffer(cls, buf): + return cls(buf.data, buf.len) + + def remaining(self): + return self.len - self.offset + + def _unpack_from(self, size, format): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + value = struct.unpack(format, self.data[self.offset:self.offset+size])[0] + self.offset += size + return value + + def read(self, size): + if self.offset + size > self.len: + raise InternalError("read past end of rust buffer") + data = self.data[self.offset:self.offset+size] + self.offset += size + return data + + def read_i8(self): + return self._unpack_from(1, ">b") + + def read_u8(self): + return self._unpack_from(1, ">B") + + def read_i16(self): + return self._unpack_from(2, ">h") + + def read_u16(self): + return self._unpack_from(2, ">H") + + def read_i32(self): + return self._unpack_from(4, ">i") + + def read_u32(self): + return self._unpack_from(4, ">I") + + def read_i64(self): + return self._unpack_from(8, ">q") + + def read_u64(self): + return self._unpack_from(8, ">Q") + + def read_float(self): + v = self._unpack_from(4, ">f") + return v + + def read_double(self): + return self._unpack_from(8, ">d") + +class _UniffiRustBufferBuilder: + """ + Helper for structured writing of bytes into a _UniffiRustBuffer. + """ + + def __init__(self): + self.rbuf = _UniffiRustBuffer.alloc(16) + self.rbuf.len = 0 + + def finalize(self): + rbuf = self.rbuf + self.rbuf = None + return rbuf + + def discard(self): + if self.rbuf is not None: + rbuf = self.finalize() + rbuf.free() + + @contextlib.contextmanager + def _reserve(self, num_bytes): + if self.rbuf.len + num_bytes > self.rbuf.capacity: + self.rbuf = _UniffiRustBuffer.reserve(self.rbuf, num_bytes) + yield None + self.rbuf.len += num_bytes + + def _pack_into(self, size, format, value): + with self._reserve(size): + # XXX TODO: I feel like I should be able to use `struct.pack_into` here but can't figure it out. + for i, byte in enumerate(struct.pack(format, value)): + self.rbuf.data[self.rbuf.len + i] = byte + + def write(self, value): + with self._reserve(len(value)): + for i, byte in enumerate(value): + self.rbuf.data[self.rbuf.len + i] = byte + + def write_i8(self, v): + self._pack_into(1, ">b", v) + + def write_u8(self, v): + self._pack_into(1, ">B", v) + + def write_i16(self, v): + self._pack_into(2, ">h", v) + + def write_u16(self, v): + self._pack_into(2, ">H", v) + + def write_i32(self, v): + self._pack_into(4, ">i", v) + + def write_u32(self, v): + self._pack_into(4, ">I", v) + + def write_i64(self, v): + self._pack_into(8, ">q", v) + + def write_u64(self, v): + self._pack_into(8, ">Q", v) + + def write_float(self, v): + self._pack_into(4, ">f", v) + + def write_double(self, v): + self._pack_into(8, ">d", v) + + def write_c_size_t(self, v): + self._pack_into(ctypes.sizeof(ctypes.c_size_t) , "@N", v) +# A handful of classes and functions to support the generated data structures. +# This would be a good candidate for isolating in its own ffi-support lib. + +class InternalError(Exception): + pass + +class _UniffiRustCallStatus(ctypes.Structure): + """ + Error runtime. + """ + _fields_ = [ + ("code", ctypes.c_int8), + ("error_buf", _UniffiRustBuffer), + ] + + # These match the values from the uniffi::rustcalls module + CALL_SUCCESS = 0 + CALL_ERROR = 1 + CALL_UNEXPECTED_ERROR = 2 + + @staticmethod + def default(): + return _UniffiRustCallStatus(code=_UniffiRustCallStatus.CALL_SUCCESS, error_buf=_UniffiRustBuffer.default()) + + def __str__(self): + if self.code == _UniffiRustCallStatus.CALL_SUCCESS: + return "_UniffiRustCallStatus(CALL_SUCCESS)" + elif self.code == _UniffiRustCallStatus.CALL_ERROR: + return "_UniffiRustCallStatus(CALL_ERROR)" + elif self.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: + return "_UniffiRustCallStatus(CALL_UNEXPECTED_ERROR)" + else: + return "_UniffiRustCallStatus()" + +def _uniffi_rust_call(fn, *args): + # Call a rust function + return _uniffi_rust_call_with_error(None, fn, *args) + +def _uniffi_rust_call_with_error(error_ffi_converter, fn, *args): + # Call a rust function and handle any errors + # + # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code. + # error_ffi_converter must be set to the _UniffiConverter for the error class that corresponds to the result. + call_status = _UniffiRustCallStatus.default() + + args_with_error = args + (ctypes.byref(call_status),) + result = fn(*args_with_error) + _uniffi_check_call_status(error_ffi_converter, call_status) + return result + +def _uniffi_check_call_status(error_ffi_converter, call_status): + if call_status.code == _UniffiRustCallStatus.CALL_SUCCESS: + pass + elif call_status.code == _UniffiRustCallStatus.CALL_ERROR: + if error_ffi_converter is None: + call_status.error_buf.free() + raise InternalError("_uniffi_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None") + else: + raise error_ffi_converter.lift(call_status.error_buf) + elif call_status.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR: + # When the rust code sees a panic, it tries to construct a _UniffiRustBuffer + # with the message. But if that code panics, then it just sends back + # an empty buffer. + if call_status.error_buf.len > 0: + msg = _UniffiConverterString.lift(call_status.error_buf) + else: + msg = "Unknown rust panic" + raise InternalError(msg) + else: + raise InternalError("Invalid _UniffiRustCallStatus code: {}".format( + call_status.code)) + +def _uniffi_trait_interface_call(call_status, make_call, write_return_value): + try: + return write_return_value(make_call()) + except Exception as e: + call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR + call_status.error_buf = _UniffiConverterString.lower(repr(e)) + +def _uniffi_trait_interface_call_with_error(call_status, make_call, write_return_value, error_type, lower_error): + try: + try: + return write_return_value(make_call()) + except error_type as e: + call_status.code = _UniffiRustCallStatus.CALL_ERROR + call_status.error_buf = lower_error(e) + except Exception as e: + call_status.code = _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR + call_status.error_buf = _UniffiConverterString.lower(repr(e)) +class _UniffiHandleMap: + """ + A map where inserting, getting and removing data is synchronized with a lock. + """ + + def __init__(self): + # type Handle = int + self._map = {} # type: Dict[Handle, Any] + self._lock = threading.Lock() + self._counter = itertools.count() + + def insert(self, obj): + with self._lock: + handle = next(self._counter) + self._map[handle] = obj + return handle + + def get(self, handle): + try: + with self._lock: + return self._map[handle] + except KeyError: + raise InternalError("_UniffiHandleMap.get: Invalid handle") + + def remove(self, handle): + try: + with self._lock: + return self._map.pop(handle) + except KeyError: + raise InternalError("_UniffiHandleMap.remove: Invalid handle") + + def __len__(self): + return len(self._map) +# Types conforming to `_UniffiConverterPrimitive` pass themselves directly over the FFI. +class _UniffiConverterPrimitive: + @classmethod + def lift(cls, value): + return value + + @classmethod + def lower(cls, value): + return value + +class _UniffiConverterPrimitiveInt(_UniffiConverterPrimitive): + @classmethod + def check_lower(cls, value): + try: + value = value.__index__() + except Exception: + raise TypeError("'{}' object cannot be interpreted as an integer".format(type(value).__name__)) + if not isinstance(value, int): + raise TypeError("__index__ returned non-int (type {})".format(type(value).__name__)) + if not cls.VALUE_MIN <= value < cls.VALUE_MAX: + raise ValueError("{} requires {} <= value < {}".format(cls.CLASS_NAME, cls.VALUE_MIN, cls.VALUE_MAX)) + +class _UniffiConverterPrimitiveFloat(_UniffiConverterPrimitive): + @classmethod + def check_lower(cls, value): + try: + value = value.__float__() + except Exception: + raise TypeError("must be real number, not {}".format(type(value).__name__)) + if not isinstance(value, float): + raise TypeError("__float__ returned non-float (type {})".format(type(value).__name__)) + +# Helper class for wrapper types that will always go through a _UniffiRustBuffer. +# Classes should inherit from this and implement the `read` and `write` static methods. +class _UniffiConverterRustBuffer: + @classmethod + def lift(cls, rbuf): + with rbuf.consume_with_stream() as stream: + return cls.read(stream) + + @classmethod + def lower(cls, value): + with _UniffiRustBuffer.alloc_with_builder() as builder: + cls.write(value, builder) + return builder.finalize() + +# Contains loading, initialization code, and the FFI Function declarations. +# Define some ctypes FFI types that we use in the library + +""" +Function pointer for a Rust task, which a callback function that takes a opaque pointer +""" +_UNIFFI_RUST_TASK = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int8) + +def _uniffi_future_callback_t(return_type): + """ + Factory function to create callback function types for async functions + """ + return ctypes.CFUNCTYPE(None, ctypes.c_uint64, return_type, _UniffiRustCallStatus) + +def _uniffi_load_indirect(): + """ + This is how we find and load the dynamic library provided by the component. + For now we just look it up by name. + """ + if sys.platform == "darwin": + libname = "lib{}.dylib" + elif sys.platform.startswith("win"): + # As of python3.8, ctypes does not seem to search $PATH when loading DLLs. + # We could use `os.add_dll_directory` to configure the search path, but + # it doesn't feel right to mess with application-wide settings. Let's + # assume that the `.dll` is next to the `.py` file and load by full path. + libname = os.path.join( + os.path.dirname(__file__), + "{}.dll", + ) + else: + # Anything else must be an ELF platform - Linux, *BSD, Solaris/illumos + libname = "lib{}.so" + + libname = libname.format("glsdk") + path = os.path.join(os.path.dirname(__file__), libname) + lib = ctypes.cdll.LoadLibrary(path) + return lib + +def _uniffi_check_contract_api_version(lib): + # Get the bindings contract version from our ComponentInterface + bindings_contract_version = 29 + # Get the scaffolding contract version by calling the into the dylib + scaffolding_contract_version = lib.ffi_glsdk_uniffi_contract_version() + if bindings_contract_version != scaffolding_contract_version: + raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") + +def _uniffi_check_api_checksums(lib): + if lib.uniffi_glsdk_checksum_method_handle_stop() != 36432: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_scheduler_recover() != 55514: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_scheduler_register() != 20821: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_signer_authenticate() != 55935: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_signer_node_id() != 43931: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_method_signer_start() != 9404: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_constructor_credentials_load() != 25306: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_constructor_node_new() != 7003: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_constructor_scheduler_new() != 15239: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_glsdk_checksum_constructor_signer_new() != 62159: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + +# A ctypes library to expose the extern-C FFI definitions. +# This is an implementation detail which will be called internally by the public API. + +_UniffiLib = _uniffi_load_indirect() +_UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK = ctypes.CFUNCTYPE(None,ctypes.c_uint64,ctypes.c_int8, +) +_UNIFFI_FOREIGN_FUTURE_FREE = ctypes.CFUNCTYPE(None,ctypes.c_uint64, +) +_UNIFFI_CALLBACK_INTERFACE_FREE = ctypes.CFUNCTYPE(None,ctypes.c_uint64, +) +class _UniffiForeignFuture(ctypes.Structure): + _fields_ = [ + ("handle", ctypes.c_uint64), + ("free", _UNIFFI_FOREIGN_FUTURE_FREE), + ] +class _UniffiForeignFutureStructU8(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_uint8), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_U8 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU8, +) +class _UniffiForeignFutureStructI8(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_int8), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_I8 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI8, +) +class _UniffiForeignFutureStructU16(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_uint16), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_U16 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU16, +) +class _UniffiForeignFutureStructI16(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_int16), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_I16 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI16, +) +class _UniffiForeignFutureStructU32(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_uint32), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_U32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU32, +) +class _UniffiForeignFutureStructI32(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_int32), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_I32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI32, +) +class _UniffiForeignFutureStructU64(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_uint64), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_U64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructU64, +) +class _UniffiForeignFutureStructI64(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_int64), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_I64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructI64, +) +class _UniffiForeignFutureStructF32(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_float), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_F32 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructF32, +) +class _UniffiForeignFutureStructF64(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_double), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_F64 = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructF64, +) +class _UniffiForeignFutureStructPointer(ctypes.Structure): + _fields_ = [ + ("return_value", ctypes.c_void_p), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_POINTER = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructPointer, +) +class _UniffiForeignFutureStructRustBuffer(ctypes.Structure): + _fields_ = [ + ("return_value", _UniffiRustBuffer), + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_RUST_BUFFER = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructRustBuffer, +) +class _UniffiForeignFutureStructVoid(ctypes.Structure): + _fields_ = [ + ("call_status", _UniffiRustCallStatus), + ] +_UNIFFI_FOREIGN_FUTURE_COMPLETE_VOID = ctypes.CFUNCTYPE(None,ctypes.c_uint64,_UniffiForeignFutureStructVoid, +) +_UniffiLib.uniffi_glsdk_fn_clone_credentials.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_credentials.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_credentials.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_credentials.restype = None +_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_clone_handle.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_handle.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_handle.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_handle.restype = None +_UniffiLib.uniffi_glsdk_fn_method_handle_stop.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_handle_stop.restype = None +_UniffiLib.uniffi_glsdk_fn_clone_node.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_node.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_node.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_node.restype = None +_UniffiLib.uniffi_glsdk_fn_constructor_node_new.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_constructor_node_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_clone_scheduler.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_scheduler.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_scheduler.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_scheduler.restype = None +_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover.argtypes = ( + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_scheduler_register.argtypes = ( + ctypes.c_void_p, + ctypes.c_void_p, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_scheduler_register.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_clone_signer.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_clone_signer.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_free_signer.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_free_signer.restype = None +_UniffiLib.uniffi_glsdk_fn_constructor_signer_new.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_constructor_signer_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate.argtypes = ( + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate.restype = ctypes.c_void_p +_UniffiLib.uniffi_glsdk_fn_method_signer_node_id.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_signer_node_id.restype = _UniffiRustBuffer +_UniffiLib.uniffi_glsdk_fn_method_signer_start.argtypes = ( + ctypes.c_void_p, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_glsdk_fn_method_signer_start.restype = ctypes.c_void_p +_UniffiLib.ffi_glsdk_rustbuffer_alloc.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rustbuffer_alloc.restype = _UniffiRustBuffer +_UniffiLib.ffi_glsdk_rustbuffer_from_bytes.argtypes = ( + _UniffiForeignBytes, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rustbuffer_from_bytes.restype = _UniffiRustBuffer +_UniffiLib.ffi_glsdk_rustbuffer_free.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rustbuffer_free.restype = None +_UniffiLib.ffi_glsdk_rustbuffer_reserve.argtypes = ( + _UniffiRustBuffer, + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rustbuffer_reserve.restype = _UniffiRustBuffer +_UniffiLib.ffi_glsdk_rust_future_poll_u8.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_u8.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_u8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_u8.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_u8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_u8.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_u8.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_u8.restype = ctypes.c_uint8 +_UniffiLib.ffi_glsdk_rust_future_poll_i8.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_i8.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_i8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_i8.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_i8.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_i8.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_i8.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_i8.restype = ctypes.c_int8 +_UniffiLib.ffi_glsdk_rust_future_poll_u16.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_u16.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_u16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_u16.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_u16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_u16.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_u16.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_u16.restype = ctypes.c_uint16 +_UniffiLib.ffi_glsdk_rust_future_poll_i16.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_i16.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_i16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_i16.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_i16.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_i16.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_i16.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_i16.restype = ctypes.c_int16 +_UniffiLib.ffi_glsdk_rust_future_poll_u32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_u32.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_u32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_u32.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_u32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_u32.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_u32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_u32.restype = ctypes.c_uint32 +_UniffiLib.ffi_glsdk_rust_future_poll_i32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_i32.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_i32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_i32.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_i32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_i32.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_i32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_i32.restype = ctypes.c_int32 +_UniffiLib.ffi_glsdk_rust_future_poll_u64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_u64.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_u64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_u64.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_u64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_u64.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_u64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_u64.restype = ctypes.c_uint64 +_UniffiLib.ffi_glsdk_rust_future_poll_i64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_i64.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_i64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_i64.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_i64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_i64.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_i64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_i64.restype = ctypes.c_int64 +_UniffiLib.ffi_glsdk_rust_future_poll_f32.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_f32.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_f32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_f32.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_f32.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_f32.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_f32.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_f32.restype = ctypes.c_float +_UniffiLib.ffi_glsdk_rust_future_poll_f64.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_f64.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_f64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_f64.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_f64.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_f64.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_f64.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_f64.restype = ctypes.c_double +_UniffiLib.ffi_glsdk_rust_future_poll_pointer.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_pointer.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_pointer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_pointer.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_pointer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_pointer.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_pointer.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_pointer.restype = ctypes.c_void_p +_UniffiLib.ffi_glsdk_rust_future_poll_rust_buffer.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_rust_buffer.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_rust_buffer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_rust_buffer.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_rust_buffer.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_rust_buffer.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_rust_buffer.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer +_UniffiLib.ffi_glsdk_rust_future_poll_void.argtypes = ( + ctypes.c_uint64, + _UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_poll_void.restype = None +_UniffiLib.ffi_glsdk_rust_future_cancel_void.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_cancel_void.restype = None +_UniffiLib.ffi_glsdk_rust_future_free_void.argtypes = ( + ctypes.c_uint64, +) +_UniffiLib.ffi_glsdk_rust_future_free_void.restype = None +_UniffiLib.ffi_glsdk_rust_future_complete_void.argtypes = ( + ctypes.c_uint64, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.ffi_glsdk_rust_future_complete_void.restype = None +_UniffiLib.uniffi_glsdk_checksum_method_handle_stop.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_handle_stop.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_scheduler_recover.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_scheduler_register.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_scheduler_register.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_signer_authenticate.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_signer_authenticate.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_signer_node_id.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_signer_node_id.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_method_signer_start.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_method_signer_start.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_constructor_credentials_load.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_constructor_credentials_load.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_constructor_node_new.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_constructor_node_new.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_constructor_scheduler_new.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_constructor_scheduler_new.restype = ctypes.c_uint16 +_UniffiLib.uniffi_glsdk_checksum_constructor_signer_new.argtypes = ( +) +_UniffiLib.uniffi_glsdk_checksum_constructor_signer_new.restype = ctypes.c_uint16 +_UniffiLib.ffi_glsdk_uniffi_contract_version.argtypes = ( +) +_UniffiLib.ffi_glsdk_uniffi_contract_version.restype = ctypes.c_uint32 + +_uniffi_check_contract_api_version(_UniffiLib) +# _uniffi_check_api_checksums(_UniffiLib) + +# Public interface members begin here. + + +class _UniffiConverterString: + @staticmethod + def check_lower(value): + if not isinstance(value, str): + raise TypeError("argument must be str, not {}".format(type(value).__name__)) + return value + + @staticmethod + def read(buf): + size = buf.read_i32() + if size < 0: + raise InternalError("Unexpected negative string length") + utf8_bytes = buf.read(size) + return utf8_bytes.decode("utf-8") + + @staticmethod + def write(value, buf): + utf8_bytes = value.encode("utf-8") + buf.write_i32(len(utf8_bytes)) + buf.write(utf8_bytes) + + @staticmethod + def lift(buf): + with buf.consume_with_stream() as stream: + return stream.read(stream.remaining()).decode("utf-8") + + @staticmethod + def lower(value): + with _UniffiRustBuffer.alloc_with_builder() as builder: + builder.write(value.encode("utf-8")) + return builder.finalize() + +class _UniffiConverterBytes(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + size = buf.read_i32() + if size < 0: + raise InternalError("Unexpected negative byte string length") + return buf.read(size) + + @staticmethod + def check_lower(value): + try: + memoryview(value) + except TypeError: + raise TypeError("a bytes-like object is required, not {!r}".format(type(value).__name__)) + + @staticmethod + def write(value, buf): + buf.write_i32(len(value)) + buf.write(value) + + + + + + + + + + + + +# Error +# We want to define each variant as a nested class that's also a subclass, +# which is tricky in Python. To accomplish this we're going to create each +# class separately, then manually add the child classes to the base class's +# __dict__. All of this happens in dummy class to avoid polluting the module +# namespace. +class Error(Exception): + pass + +_UniffiTempError = Error + +class Error: # type: ignore + class DuplicateNode(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.DuplicateNode({})".format(str(self)) + _UniffiTempError.DuplicateNode = DuplicateNode # type: ignore + class NoSuchNode(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.NoSuchNode({})".format(str(self)) + _UniffiTempError.NoSuchNode = NoSuchNode # type: ignore + class UnparseableCreds(_UniffiTempError): + def __init__(self): + pass + + def __repr__(self): + return "Error.UnparseableCreds({})".format(str(self)) + _UniffiTempError.UnparseableCreds = UnparseableCreds # type: ignore + class PhraseCorrupted(_UniffiTempError): + def __init__(self): + pass + + def __repr__(self): + return "Error.PhraseCorrupted({})".format(str(self)) + _UniffiTempError.PhraseCorrupted = PhraseCorrupted # type: ignore + class Other(_UniffiTempError): + def __init__(self, *values): + if len(values) != 1: + raise TypeError(f"Expected 1 arguments, found {len(values)}") + if not isinstance(values[0], str): + raise TypeError(f"unexpected type for tuple element 0 - expected 'str', got '{type(values[0])}'") + super().__init__(", ".join(map(repr, values))) + self._values = values + + def __getitem__(self, index): + return self._values[index] + + def __repr__(self): + return "Error.Other({})".format(str(self)) + _UniffiTempError.Other = Other # type: ignore + +Error = _UniffiTempError # type: ignore +del _UniffiTempError + + +class _UniffiConverterTypeError(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return Error.DuplicateNode( + _UniffiConverterString.read(buf), + ) + if variant == 2: + return Error.NoSuchNode( + _UniffiConverterString.read(buf), + ) + if variant == 3: + return Error.UnparseableCreds( + ) + if variant == 4: + return Error.PhraseCorrupted( + ) + if variant == 5: + return Error.Other( + _UniffiConverterString.read(buf), + ) + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if isinstance(value, Error.DuplicateNode): + _UniffiConverterString.check_lower(value._values[0]) + return + if isinstance(value, Error.NoSuchNode): + _UniffiConverterString.check_lower(value._values[0]) + return + if isinstance(value, Error.UnparseableCreds): + return + if isinstance(value, Error.PhraseCorrupted): + return + if isinstance(value, Error.Other): + _UniffiConverterString.check_lower(value._values[0]) + return + + @staticmethod + def write(value, buf): + if isinstance(value, Error.DuplicateNode): + buf.write_i32(1) + _UniffiConverterString.write(value._values[0], buf) + if isinstance(value, Error.NoSuchNode): + buf.write_i32(2) + _UniffiConverterString.write(value._values[0], buf) + if isinstance(value, Error.UnparseableCreds): + buf.write_i32(3) + if isinstance(value, Error.PhraseCorrupted): + buf.write_i32(4) + if isinstance(value, Error.Other): + buf.write_i32(5) + _UniffiConverterString.write(value._values[0], buf) + + + + + +class Network(enum.Enum): + BITCOIN = 0 + + REGTEST = 1 + + + +class _UniffiConverterTypeNetwork(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return Network.BITCOIN + if variant == 2: + return Network.REGTEST + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == Network.BITCOIN: + return + if value == Network.REGTEST: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == Network.BITCOIN: + buf.write_i32(1) + if value == Network.REGTEST: + buf.write_i32(2) + + + + + +class _UniffiConverterOptionalString(_UniffiConverterRustBuffer): + @classmethod + def check_lower(cls, value): + if value is not None: + _UniffiConverterString.check_lower(value) + + @classmethod + def write(cls, value, buf): + if value is None: + buf.write_u8(0) + return + + buf.write_u8(1) + _UniffiConverterString.write(value, buf) + + @classmethod + def read(cls, buf): + flag = buf.read_u8() + if flag == 0: + return None + elif flag == 1: + return _UniffiConverterString.read(buf) + else: + raise InternalError("Unexpected flag byte for optional type") + +# objects. +class CredentialsProtocol(typing.Protocol): + """ + `Credentials` is a container for `node_id`, the mTLS client + certificate used to authenticate a client against a node, as well + as the seed secret if present. If no seed is present in the + credentials, then the `Client` will not start a signer in the + background. + """ + + pass +# Credentials is a Rust-only trait - it's a wrapper around a Rust implementation. +class Credentials(): + """ + `Credentials` is a container for `node_id`, the mTLS client + certificate used to authenticate a client against a node, as well + as the seed secret if present. If no seed is present in the + credentials, then the `Client` will not start a signer in the + background. + """ + + _pointer: ctypes.c_void_p + + def __init__(self, *args, **kwargs): + raise ValueError("This class has no default constructor") + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_credentials, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_credentials, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + @classmethod + def load(cls, raw: "bytes"): + _UniffiConverterBytes.check_lower(raw) + + # Call the (fallible) function before creating any half-baked object instances. + pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_credentials_load, + _UniffiConverterBytes.lower(raw)) + return cls._make_instance_(pointer) + + + + +class _UniffiConverterTypeCredentials: + + @staticmethod + def lift(value: int): + return Credentials._make_instance_(value) + + @staticmethod + def check_lower(value: Credentials): + if not isinstance(value, Credentials): + raise TypeError("Expected Credentials instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: CredentialsProtocol): + if not isinstance(value, Credentials): + raise TypeError("Expected Credentials instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: CredentialsProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) +class HandleProtocol(typing.Protocol): + """ + A handle to interact with a signer loop running and processing + requests in the background. Used primarily to stop the loop and + exiting the signer. + """ + + def stop(self, ): + raise NotImplementedError +# Handle is a Rust-only trait - it's a wrapper around a Rust implementation. +class Handle(): + """ + A handle to interact with a signer loop running and processing + requests in the background. Used primarily to stop the loop and + exiting the signer. + """ + + _pointer: ctypes.c_void_p + + def __init__(self, *args, **kwargs): + raise ValueError("This class has no default constructor") + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_handle, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_handle, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + + + def stop(self, ) -> None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_method_handle_stop,self._uniffi_clone_pointer(),) + + + + + + + +class _UniffiConverterTypeHandle: + + @staticmethod + def lift(value: int): + return Handle._make_instance_(value) + + @staticmethod + def check_lower(value: Handle): + if not isinstance(value, Handle): + raise TypeError("Expected Handle instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: HandleProtocol): + if not isinstance(value, Handle): + raise TypeError("Expected Handle instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: HandleProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) +class NodeProtocol(typing.Protocol): + """ + The `Node` is an RPC stub representing the node running in the + cloud. It is the main entrypoint to interact with the node. + """ + + pass +# Node is a Rust-only trait - it's a wrapper around a Rust implementation. +class Node(): + """ + The `Node` is an RPC stub representing the node running in the + cloud. It is the main entrypoint to interact with the node. + """ + + _pointer: ctypes.c_void_p + def __init__(self, credentials: "Credentials"): + _UniffiConverterTypeCredentials.check_lower(credentials) + + self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_node_new, + _UniffiConverterTypeCredentials.lower(credentials)) + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_node, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_node, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + + + +class _UniffiConverterTypeNode: + + @staticmethod + def lift(value: int): + return Node._make_instance_(value) + + @staticmethod + def check_lower(value: Node): + if not isinstance(value, Node): + raise TypeError("Expected Node instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: NodeProtocol): + if not isinstance(value, Node): + raise TypeError("Expected Node instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: NodeProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) +class SchedulerProtocol(typing.Protocol): + def recover(self, signer: "Signer"): + raise NotImplementedError + def register(self, signer: "Signer",code: "typing.Optional[str]"): + raise NotImplementedError +# Scheduler is a Rust-only trait - it's a wrapper around a Rust implementation. +class Scheduler(): + _pointer: ctypes.c_void_p + def __init__(self, network: "Network"): + """ + Create a `Scheduler` instance configured with the Greenlight + production service pre-configured. + """ + + _UniffiConverterTypeNetwork.check_lower(network) + + self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_scheduler_new, + _UniffiConverterTypeNetwork.lower(network)) + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_scheduler, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_scheduler, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + + + def recover(self, signer: "Signer") -> "Credentials": + _UniffiConverterTypeSigner.check_lower(signer) + + return _UniffiConverterTypeCredentials.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_scheduler_recover,self._uniffi_clone_pointer(), + _UniffiConverterTypeSigner.lower(signer)) + ) + + + + + + def register(self, signer: "Signer",code: "typing.Optional[str]") -> "Credentials": + _UniffiConverterTypeSigner.check_lower(signer) + + _UniffiConverterOptionalString.check_lower(code) + + return _UniffiConverterTypeCredentials.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_scheduler_register,self._uniffi_clone_pointer(), + _UniffiConverterTypeSigner.lower(signer), + _UniffiConverterOptionalString.lower(code)) + ) + + + + + + +class _UniffiConverterTypeScheduler: + + @staticmethod + def lift(value: int): + return Scheduler._make_instance_(value) + + @staticmethod + def check_lower(value: Scheduler): + if not isinstance(value, Scheduler): + raise TypeError("Expected Scheduler instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: SchedulerProtocol): + if not isinstance(value, Scheduler): + raise TypeError("Expected Scheduler instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: SchedulerProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) +class SignerProtocol(typing.Protocol): + def authenticate(self, creds: "Credentials"): + raise NotImplementedError + def node_id(self, ): + raise NotImplementedError + def start(self, ): + raise NotImplementedError +# Signer is a Rust-only trait - it's a wrapper around a Rust implementation. +class Signer(): + _pointer: ctypes.c_void_p + def __init__(self, phrase: "str"): + _UniffiConverterString.check_lower(phrase) + + self._pointer = _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_constructor_signer_new, + _UniffiConverterString.lower(phrase)) + + def __del__(self): + # In case of partial initialization of instances. + pointer = getattr(self, "_pointer", None) + if pointer is not None: + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_free_signer, pointer) + + def _uniffi_clone_pointer(self): + return _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_clone_signer, self._pointer) + + # Used by alternative constructors or any methods which return this type. + @classmethod + def _make_instance_(cls, pointer): + # Lightly yucky way to bypass the usual __init__ logic + # and just create a new instance with the required pointer. + inst = cls.__new__(cls) + inst._pointer = pointer + return inst + + + def authenticate(self, creds: "Credentials") -> "Signer": + _UniffiConverterTypeCredentials.check_lower(creds) + + return _UniffiConverterTypeSigner.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_signer_authenticate,self._uniffi_clone_pointer(), + _UniffiConverterTypeCredentials.lower(creds)) + ) + + + + + + def node_id(self, ) -> "bytes": + return _UniffiConverterBytes.lift( + _uniffi_rust_call(_UniffiLib.uniffi_glsdk_fn_method_signer_node_id,self._uniffi_clone_pointer(),) + ) + + + + + + def start(self, ) -> "Handle": + return _UniffiConverterTypeHandle.lift( + _uniffi_rust_call_with_error(_UniffiConverterTypeError,_UniffiLib.uniffi_glsdk_fn_method_signer_start,self._uniffi_clone_pointer(),) + ) + + + + + + +class _UniffiConverterTypeSigner: + + @staticmethod + def lift(value: int): + return Signer._make_instance_(value) + + @staticmethod + def check_lower(value: Signer): + if not isinstance(value, Signer): + raise TypeError("Expected Signer instance, {} found".format(type(value).__name__)) + + @staticmethod + def lower(value: SignerProtocol): + if not isinstance(value, Signer): + raise TypeError("Expected Signer instance, {} found".format(type(value).__name__)) + return value._uniffi_clone_pointer() + + @classmethod + def read(cls, buf: _UniffiRustBuffer): + ptr = buf.read_u64() + if ptr == 0: + raise InternalError("Raw pointer value was null") + return cls.lift(ptr) + + @classmethod + def write(cls, value: SignerProtocol, buf: _UniffiRustBuffer): + buf.write_u64(cls.lower(value)) + +# Async support + +__all__ = [ + "InternalError", + "Error", + "Network", + "Credentials", + "Handle", + "Node", + "Scheduler", + "Signer", +] + diff --git a/libs/gl-sdk/pyproject.toml b/libs/gl-sdk/pyproject.toml new file mode 100644 index 000000000..8ec58e643 --- /dev/null +++ b/libs/gl-sdk/pyproject.toml @@ -0,0 +1,39 @@ +[project] +name = "gl-sdk" +version = "0.1.0" +description = "Python bindings for Greenlight SDK using UniFFI" +readme = "README.md" +requires-python = ">=3.10" +dependencies = [] +authors = [ + {name = "Christian Decker", email = "decker@blockstream.com"}, +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["glsdk"] + +# Include the shared library as package data +[tool.hatch.build.targets.wheel.force-include] +"glsdk/libglsdk.so" = "glsdk/libglsdk.so" + +[dependency-groups] +dev = [ + "gl-testing", + "pdoc>=15.0.4", + "pytest>=7.0", + "pytest-watcher>=0.4.3", + "rich>=10.0", +] + +[tool.uv.sources] +gl-testing = { workspace = true } + +[tool.pytest.ini_options] +testpaths = ["tests"] +python_files = ["test_*.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] diff --git a/libs/gl-sdk/src/credentials.rs b/libs/gl-sdk/src/credentials.rs new file mode 100644 index 000000000..d07637068 --- /dev/null +++ b/libs/gl-sdk/src/credentials.rs @@ -0,0 +1,22 @@ +use crate::Error; +use gl_client::credentials::Device as DeviceCredentials; + +/// `Credentials` is a container for `node_id`, the mTLS client +/// certificate used to authenticate a client against a node, as well +/// as the seed secret if present. If no seed is present in the +/// credentials, then the `Client` will not start a signer in the +/// background. +#[derive(uniffi::Object, Clone)] +pub struct Credentials { + pub(crate) inner: DeviceCredentials, +} + +#[uniffi::export] +impl Credentials { + #[uniffi::constructor()] + pub(crate) fn load(raw: Vec) -> Result { + Ok(Self { + inner: DeviceCredentials::from_bytes(raw), + }) + } +} diff --git a/libs/gl-sdk/src/lib.rs b/libs/gl-sdk/src/lib.rs new file mode 100644 index 000000000..cdfe15a13 --- /dev/null +++ b/libs/gl-sdk/src/lib.rs @@ -0,0 +1,46 @@ +uniffi::setup_scaffolding!(); + +#[derive(uniffi::Error, thiserror::Error, Debug)] +pub enum Error { + #[error("There is already a node for node_id={0}, maybe you want to recover?")] + DuplicateNode(String), + + #[error("There is no node with node_id={0}, maybe you need to register first?")] + NoSuchNode(String), + + #[error("The provided credentials could not be parsed, please recover.")] + UnparseableCreds(), + + #[error("The passphrase you provided fails the checksum")] + PhraseCorrupted(), + + #[error("Generic error: {0}")] + Other(String), +} +mod credentials; +mod node; +mod scheduler; +mod signer; +mod util; + +pub use crate::{ + credentials::Credentials, + node::Node, + scheduler::Scheduler, + signer::{Handle, Signer}, +}; + +#[derive(uniffi::Enum, Debug)] +pub enum Network { + BITCOIN, + REGTEST, +} + +impl From for gl_client::bitcoin::Network { + fn from(n: Network) -> gl_client::bitcoin::Network { + match n { + Network::BITCOIN => gl_client::bitcoin::Network::Bitcoin, + Network::REGTEST => gl_client::bitcoin::Network::Regtest, + } + } +} diff --git a/libs/gl-sdk/src/node.rs b/libs/gl-sdk/src/node.rs new file mode 100644 index 000000000..b1f83648c --- /dev/null +++ b/libs/gl-sdk/src/node.rs @@ -0,0 +1,26 @@ +use crate::{Error, credentials::Credentials}; +use gl_client::node::Node as ClientNode; +use gl_client::credentials::NodeIdProvider; + +/// The `Node` is an RPC stub representing the node running in the +/// cloud. It is the main entrypoint to interact with the node. +#[derive(uniffi::Object)] +#[allow(unused)] +pub struct Node { + inner: ClientNode, +} + +#[uniffi::export] +impl Node { + #[uniffi::constructor()] + pub fn new(credentials: &Credentials) -> Result { + let node_id = credentials + .inner + .node_id() + .map_err(|_e| Error::UnparseableCreds())?; + let client = ClientNode::new(node_id, credentials.inner.clone()) + .expect("infallible client instantiation"); + + Ok(Node { inner: client }) + } +} diff --git a/libs/gl-sdk/src/scheduler.rs b/libs/gl-sdk/src/scheduler.rs new file mode 100644 index 000000000..172c406d4 --- /dev/null +++ b/libs/gl-sdk/src/scheduler.rs @@ -0,0 +1,61 @@ +use crate::{credentials::Credentials, signer::Signer, util::exec, Error}; + +#[derive(uniffi::Object, Clone)] +pub struct Scheduler { + credentials: Option, + network: gl_client::bitcoin::Network, +} + +#[uniffi::export] +impl Scheduler { + /// Create a `Scheduler` instance configured with the Greenlight + /// production service pre-configured. + #[uniffi::constructor()] + pub fn new(network: crate::Network) -> Result { + // We use the nobody credentials since there is no + // authenticated method we expose at the moment. + let creds = None; + let network: gl_client::bitcoin::Network = network.into(); + + Ok(Scheduler { + credentials: creds, + network, + }) + } + + pub fn register(&self, signer: &Signer, code: Option) -> Result { + exec(async move { + let inner = gl_client::scheduler::Scheduler::new( + self.network, + gl_client::credentials::Nobody::new(), + ) + .await + .map_err(|e| Error::Other(e.to_string()))?; + + let res = inner + .register(&signer.inner, code) + .await + .map_err(|e| Error::Other(e.to_string().clone()))?; + + Credentials::load(res.creds).map_err(|_e| Error::UnparseableCreds()) + }) + } + + pub fn recover(&self, signer: &Signer) -> Result { + exec(async move { + let inner = gl_client::scheduler::Scheduler::new( + self.network, + gl_client::credentials::Nobody::new(), + ) + .await + .map_err(|e| Error::Other(e.to_string()))?; + + let res = inner + .recover(&signer.inner) + .await + .map_err(|e| Error::Other(e.to_string()))?; + + Credentials::load(res.creds).map_err(|_e| Error::UnparseableCreds()) + }) + } +} diff --git a/libs/gl-sdk/src/signer.rs b/libs/gl-sdk/src/signer.rs new file mode 100644 index 000000000..70e7d6ceb --- /dev/null +++ b/libs/gl-sdk/src/signer.rs @@ -0,0 +1,90 @@ +use crate::{Credentials, Error}; +use bip39::{Language, Mnemonic}; +use std::str::FromStr; + +#[derive(uniffi::Object, Clone)] +pub struct Signer { + seed: Vec, + pub(crate) inner: gl_client::signer::Signer, + credentials: Option, +} + +#[uniffi::export] +impl Signer { + #[uniffi::constructor()] + fn new(phrase: String) -> Result { + let phrase = Mnemonic::from_str(phrase.as_str()).map_err(|e| Error::PhraseCorrupted())?; + let seed = phrase.to_seed_normalized(&"").to_vec(); + + // FIXME: We may need to give the signer real credentials to + // talk to the node too. + let credentials = gl_client::credentials::Nobody::new(); + + let inner = gl_client::signer::Signer::new( + seed.clone(), + gl_client::bitcoin::Network::Bitcoin, + credentials, + ) + .map_err(|e| Error::Other(e.to_string()))?; + let credentials = None; + Ok(Signer { + seed, + inner, + credentials, + }) + } + + fn authenticate(&self, creds: &Credentials) -> Result { + let credentials = Some(creds.clone()); + + let inner = gl_client::signer::Signer::new( + self.seed.clone(), + gl_client::bitcoin::Network::Bitcoin, + creds.inner.clone(), + ) + .map_err(|e| Error::Other(e.to_string()))?; + + Ok(Signer { + inner, + credentials, + ..self.clone() + }) + } + + fn start(&self) -> Result { + let (mut tx, mut rx) = tokio::sync::mpsc::channel(1); + + let clone = self.clone(); + tokio::spawn(async move { + clone.run(rx).await; + }); + + Ok(Handle { chan: tx }) + } + + fn node_id(&self) -> Vec { + unimplemented!() + } +} + +// Not exported through uniffi, internal logic only. +impl Signer { + async fn run(&self, signal: tokio::sync::mpsc::Receiver<()>) { + self.inner.run_forever(signal).await.expect("Error running signer loop"); + } +} + +/// A handle to interact with a signer loop running and processing +/// requests in the background. Used primarily to stop the loop and +/// exiting the signer. +#[derive(uniffi::Object, Clone)] +pub struct Handle { + chan: tokio::sync::mpsc::Sender<()>, +} + +#[uniffi::export] +impl Handle { + pub fn stop(&self) { + self.chan.try_send(()).expect("sending shutdown signal"); + } +} diff --git a/libs/gl-sdk/src/util.rs b/libs/gl-sdk/src/util.rs new file mode 100644 index 000000000..0289f0c39 --- /dev/null +++ b/libs/gl-sdk/src/util.rs @@ -0,0 +1,21 @@ +use ::tokio::runtime::{Builder, Runtime}; +use once_cell::sync::OnceCell; +use std::future::Future; + +static TOKIO_RUNTIME: OnceCell = OnceCell::new(); + +pub(crate) fn get_runtime<'a>() -> &'a Runtime { + TOKIO_RUNTIME.get_or_init(|| { + let mut builder = Builder::new_multi_thread(); + builder.enable_all(); + builder.build().expect("Unable to build Tokio runtime") + }) +} + +pub(crate) fn exec(f: F) -> T +where + F: Future + Sized + Send, + T: Send, +{ + get_runtime().block_on(f) +} diff --git a/libs/gl-sdk/tests/test_basic.py b/libs/gl-sdk/tests/test_basic.py new file mode 100644 index 000000000..76699648e --- /dev/null +++ b/libs/gl-sdk/tests/test_basic.py @@ -0,0 +1,68 @@ +"""Basic tests for gl-sdk without requiring full scheduler setup. + +These tests verify the UniFFI bindings work correctly without +needing the full gl-testing infrastructure. +""" + +from gltesting.fixtures import * +import pytest +import glsdk + + +def test_import_glsdk(): + """Test that glsdk can be imported.""" + assert glsdk is not None + assert hasattr(glsdk, "Credentials") + assert hasattr(glsdk, "Node") + assert hasattr(glsdk, "Signer") + assert hasattr(glsdk, "Error") + + +def test_credentials_load_empty(): + """Test loading credentials with empty data doesn't crash.""" + # This should not crash - Device::from_bytes defaults to nobody creds + credentials = glsdk.Credentials.load(b"") + assert credentials is not None + assert isinstance(credentials, glsdk.Credentials) + + +def test_credentials_load_invalid(): + """Test loading credentials with invalid data doesn't crash.""" + # This should not crash either + credentials = glsdk.Credentials.load(b"invalid data") + assert credentials is not None + + +def test_credentials_type_error(): + """Test that passing wrong type raises TypeError.""" + with pytest.raises(TypeError): + glsdk.Credentials.load("not bytes") + + +def test_credentials_multiple_loads(): + """Test that we can create multiple credentials objects.""" + creds1 = glsdk.Credentials.load(b"test1") + creds2 = glsdk.Credentials.load(b"test2") + creds3 = glsdk.Credentials.load(b"test3") + + assert all(isinstance(c, glsdk.Credentials) for c in [creds1, creds2, creds3]) + + +def test_node_creation_fails_with_empty_creds(): + """Test that creating a Node with empty credentials fails as expected.""" + creds = glsdk.Credentials.load(b"") + + # Node creation should fail with these invalid credentials + with pytest.raises(glsdk.Error): + node = glsdk.Node(creds) + + +def test_register_and_auth(scheduler, clients): + signer = glsdk.Signer( + "abandon abandon abandon abandon abandon abandon " + "abandon abandon abandon abandon abandon about" + ) + + # Now use the signer to sign up a new node: + scheduler = glsdk.Scheduler(glsdk.Network.BITCOIN) + creds = scheduler.register(signer, code=None) diff --git a/libs/gl-sdk/tests/test_credentials.py b/libs/gl-sdk/tests/test_credentials.py new file mode 100644 index 000000000..3dd12c7af --- /dev/null +++ b/libs/gl-sdk/tests/test_credentials.py @@ -0,0 +1,129 @@ +"""Tests for gl-sdk Credentials wrapper around gl-client credentials. + +This test suite validates that the UniFFI-exposed Credentials struct +correctly wraps the underlying gl-client Device credentials and can +load credentials data from disk. +""" +import pytest +import glsdk +from gltesting.fixtures import * + + +def test_credentials_load_from_registered_client(scheduler, clients): + """Load credentials from a registered client's greenlight.auth file. + + This test verifies that after a client registers with the scheduler, + the credentials file can be successfully loaded via the gl-sdk + Credentials.load() method exposed through UniFFI. + """ + # Create a new client and register it + c = clients.new() + c.register(configure=True) + + # Verify the credentials file was created + creds_path = c.directory / "greenlight.auth" + assert creds_path.exists(), "greenlight.auth file should exist after registration" + + # Read the credentials file + creds_bytes = creds_path.read_bytes() + assert len(creds_bytes) > 0, "Credentials file should not be empty" + + # Load credentials using the gl-sdk UniFFI wrapper + credentials = glsdk.Credentials.load(creds_bytes) + + # Verify we got a valid Credentials object + assert credentials is not None + assert isinstance(credentials, glsdk.Credentials) + + +def test_credentials_load_empty_data(scheduler, clients): + """Verify that loading credentials with empty data doesn't crash. + + The underlying gl-client Device::from_bytes implementation defaults + to nobody credentials when given invalid/empty data, so this should + succeed but return a default credentials object. + """ + # Create empty credentials data + empty_data = b"" + + # This should not crash - Device::from_bytes defaults to nobody creds + credentials = glsdk.Credentials.load(empty_data) + assert credentials is not None + assert isinstance(credentials, glsdk.Credentials) + + +def test_credentials_load_invalid_data(scheduler, clients): + """Test that loading completely invalid data doesn't crash. + + The underlying implementation should handle invalid data gracefully + by falling back to default nobody credentials. + """ + # Create some random invalid data + invalid_data = b"not valid credentials data at all!" + + # This should not crash + credentials = glsdk.Credentials.load(invalid_data) + assert credentials is not None + + +def test_credentials_multiple_loads(scheduler, clients): + """Verify that the same credentials data can be loaded multiple times. + + This ensures there are no issues with resource ownership or + cleanup when creating multiple Credentials instances from the same data. + """ + c = clients.new() + c.register(configure=True) + + creds_bytes = (c.directory / "greenlight.auth").read_bytes() + + # Load the same credentials multiple times + creds1 = glsdk.Credentials.load(creds_bytes) + creds2 = glsdk.Credentials.load(creds_bytes) + creds3 = glsdk.Credentials.load(creds_bytes) + + # All should be valid Credentials objects + assert isinstance(creds1, glsdk.Credentials) + assert isinstance(creds2, glsdk.Credentials) + assert isinstance(creds3, glsdk.Credentials) + + +def test_credentials_from_recovered_client(scheduler, clients): + """Test loading credentials from a recovered client. + + This verifies that credentials work correctly through the + recovery flow, not just registration. + """ + # Create a client and register + secret = bytes([42] * 32) + c1 = clients.new(secret=secret) + c1.register(configure=False) + + # Create a new client with the same secret and recover + c2 = clients.new(secret=secret) + c2.recover(configure=True) + + # Load credentials from the recovered client + creds_path = c2.directory / "greenlight.auth" + assert creds_path.exists() + + creds_bytes = creds_path.read_bytes() + credentials = glsdk.Credentials.load(creds_bytes) + + assert credentials is not None + assert isinstance(credentials, glsdk.Credentials) + + +# Intentionally failing test to demonstrate error handling +def test_credentials_type_error_fails(): + """This test should fail: passing wrong type to Credentials.load(). + + UniFFI should raise a TypeError when we pass a string instead of bytes. + This test demonstrates proper error handling and type checking. + """ + with pytest.raises(TypeError) as exc_info: + # This should fail - we're passing a string, not bytes + glsdk.Credentials.load("this is a string, not bytes") + + # Verify we get a helpful error message about type mismatch + assert "bytes" in str(exc_info.value).lower() or "type" in str(exc_info.value).lower() diff --git a/libs/gl-sdk/tests/test_scheduler.py b/libs/gl-sdk/tests/test_scheduler.py new file mode 100644 index 000000000..74be9073a --- /dev/null +++ b/libs/gl-sdk/tests/test_scheduler.py @@ -0,0 +1,10 @@ +"""Testing client-scheduler interactions +""" + +import pytest +import glsdk +from gltesting.fixtures import * + +def test_register(scheduler, clients): + signer = glsdk.Signer("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about") + diff --git a/libs/uniffi-bindgen/Cargo.toml b/libs/uniffi-bindgen/Cargo.toml new file mode 100644 index 000000000..0df97517d --- /dev/null +++ b/libs/uniffi-bindgen/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "uniffi-bindgen" +version = "0.1.0" +edition = "2024" + +[[bin]] +# This can be whatever name makes sense for your project, but the rest of this tutorial assumes uniffi-bindgen. +name = "uniffi-bindgen" +path = "src/main.rs" + +[dependencies] +uniffi = {version = "0.29.4", features = ["cli"] } diff --git a/libs/uniffi-bindgen/src/main.rs b/libs/uniffi-bindgen/src/main.rs new file mode 100644 index 000000000..f6cff6cf1 --- /dev/null +++ b/libs/uniffi-bindgen/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + uniffi::uniffi_bindgen_main() +} diff --git a/pyproject.toml b/pyproject.toml index b8a3beabe..2b9433964 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,5 +21,6 @@ members = [ "libs/gl-client-py", "libs/gl-testserver", "libs/cln-version-manager", + "libs/gl-sdk", ] exclude = ["packages/seeds"] From 2c8e370c6cbb7b76fed98b4dbf91594601bb2f2b Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 19 Nov 2025 11:20:42 +0100 Subject: [PATCH 3/5] chore(rs): Address a lint regarding useless parentheses --- libs/gl-client/src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gl-client/src/utils.rs b/libs/gl-client/src/utils.rs index 40883cc14..c6622c20e 100644 --- a/libs/gl-client/src/utils.rs +++ b/libs/gl-client/src/utils.rs @@ -31,7 +31,7 @@ pub fn get_node_id_from_tls_config(tls_config: &TlsConfig) -> Result> { "Could not parse subject common name: {}", subject_common_name )); - } else if (split_subject_common_name[1] != "users") { + } else if split_subject_common_name[1] != "users" { return Err(anyhow!("Not a users certificate: {}", subject_common_name)); } From 75af5ec0e88bb560831648801205190ca64eabd2 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 19 Nov 2025 17:08:55 +0100 Subject: [PATCH 4/5] sdk: Implement the `stop()` method --- Taskfile.yml | 1 + libs/gl-plugin/src/requests.rs | 6 +- libs/gl-sdk/src/credentials.rs | 4 ++ libs/gl-sdk/src/lib.rs | 3 + libs/gl-sdk/src/node.rs | 127 +++++++++++++++++++++++++++++++-- 5 files changed, 133 insertions(+), 8 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index d923319ad..d6e3d8f82 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -34,6 +34,7 @@ tasks: deps: - ci-build cmds: + - task: sdk:test - task: clientpy:check - task: testing:check - task: clnvm:check diff --git a/libs/gl-plugin/src/requests.rs b/libs/gl-plugin/src/requests.rs index e2344b408..5d24713d6 100644 --- a/libs/gl-plugin/src/requests.rs +++ b/libs/gl-plugin/src/requests.rs @@ -250,10 +250,10 @@ impl From for LspInvoiceRequest { impl TypedRequest for LspInvoiceRequest { type Response = super::responses::InvoiceResponse; fn method(&self) -> &str { - // TODO Rename after the CLN rename has been deployed. + // TODO Rename after the CLN rename has been deployed. // "lsps-lsps2-invoice" - "lsps-jitchannel" - } + "lsps-jitchannel" + } } impl TypedRequest for LspGetinfoRequest { diff --git a/libs/gl-sdk/src/credentials.rs b/libs/gl-sdk/src/credentials.rs index d07637068..c920a9013 100644 --- a/libs/gl-sdk/src/credentials.rs +++ b/libs/gl-sdk/src/credentials.rs @@ -19,4 +19,8 @@ impl Credentials { inner: DeviceCredentials::from_bytes(raw), }) } + + pub(crate) fn save(&self) -> Result, Error> { + Ok(self.inner.to_bytes()) + } } diff --git a/libs/gl-sdk/src/lib.rs b/libs/gl-sdk/src/lib.rs index cdfe15a13..6d0f766a0 100644 --- a/libs/gl-sdk/src/lib.rs +++ b/libs/gl-sdk/src/lib.rs @@ -14,6 +14,9 @@ pub enum Error { #[error("The passphrase you provided fails the checksum")] PhraseCorrupted(), + #[error("Error calling the rpc: {0}")] + Rpc(String), + #[error("Generic error: {0}")] Other(String), } diff --git a/libs/gl-sdk/src/node.rs b/libs/gl-sdk/src/node.rs index b1f83648c..45721bc32 100644 --- a/libs/gl-sdk/src/node.rs +++ b/libs/gl-sdk/src/node.rs @@ -1,13 +1,18 @@ -use crate::{Error, credentials::Credentials}; -use gl_client::node::Node as ClientNode; +use crate::{credentials::Credentials, util::exec, Error}; use gl_client::credentials::NodeIdProvider; +use gl_client::node::{Client as GlClient, ClnClient, Node as ClientNode}; + +use gl_client::pb::cln as clnpb; +use tokio::sync::OnceCell; /// The `Node` is an RPC stub representing the node running in the /// cloud. It is the main entrypoint to interact with the node. -#[derive(uniffi::Object)] +#[derive(uniffi::Object, Clone)] #[allow(unused)] pub struct Node { inner: ClientNode, + cln_client: OnceCell, + gl_client: OnceCell, } #[uniffi::export] @@ -18,9 +23,121 @@ impl Node { .inner .node_id() .map_err(|_e| Error::UnparseableCreds())?; - let client = ClientNode::new(node_id, credentials.inner.clone()) + let inner = ClientNode::new(node_id, credentials.inner.clone()) .expect("infallible client instantiation"); - Ok(Node { inner: client }) + let cln_client = OnceCell::const_new(); + let gl_client = OnceCell::const_new(); + Ok(Node { + inner, + cln_client, + gl_client, + }) + } + + pub fn stop(&self) -> Result<(), Error> { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::StopRequest {}; + + // It's ok, the error here is expected and should just be + // telling us that we've lost the connection. This is to + // be expected on shutdown, so we clamp this to success. + exec(cln_client.stop(req)); + Ok(()) + } + + /// Receive an off-chain payment. + /// + /// This method generates a request for a payment, also called an + /// invoice, that encodes all the information, including amount + /// and destination, for a prospective sender to send a lightning + /// payment. The invoice includes negotiation of an LSPS2 / JIT + /// channel, meaning that if there is no channel sufficient to + /// receive the requested funds, the node will negotiate an + /// opening, and when/if executed the payment will cause a channel + /// to be created, and the incoming payment to be forwarded. + fn receive( + &self, + label: String, + description: String, + amount_msat: Option, + ) -> Result { + let mut gl_client = exec(self.get_gl_client())?.clone(); + + let req = gl_client::pb::LspInvoiceRequest { + amount_msat: amount_msat.unwrap_or_default(), + description: description, + label: label, + lsp_id: "".to_owned(), + token: "".to_owned(), + }; + let res = exec(gl_client.lsp_invoice(req)) + .map_err(|s| Error::Rpc(s.to_string()))? + .into_inner(); + Ok(ReceiveResponse { bolt11: res.bolt11 }) + } + + fn onchain_send(&self, req: &OnchainSendRequest) -> Result { + unimplemented!() + } + fn onchain_receive( + &self, + addresstype: Option, + ) -> Result { + unimplemented!() + } + + fn send(&self, invoice: String) -> SendResponse { + unimplemented!() + } +} + +// Not exported through uniffi +impl Node { + async fn get_gl_client<'a>(&'a self) -> Result<&'a GlClient, Error> { + let inner = self.inner.clone(); + self.gl_client + .get_or_try_init(|| async { inner.schedule::().await }) + .await + .map_err(|e| Error::Rpc(e.to_string())) + } + + async fn get_cln_client<'a>(&'a self) -> Result<&'a ClnClient, Error> { + let inner = self.inner.clone(); + + self.cln_client + .get_or_try_init(|| async { inner.schedule::().await }) + .await + .map_err(|e| Error::Rpc(e.to_string())) } } + +#[derive(uniffi::Object)] +struct OnchainSendResponse {} + +#[derive(uniffi::Object)] +struct OnchainSendRequest { + label: String, + description: String, + amount_msat: Option, +} + +#[derive(uniffi::Enum)] +enum AddressType { + BECH32, + P2TR, +} + +#[derive(uniffi::Object)] +struct OnchainReceiveResponse { + address: String, +} + +#[derive(uniffi::Object)] +struct SendResponse {} + +#[derive(uniffi::Object)] +struct ReceiveResponse { + bolt11: String, +} From df3150b85943a72399f6683f21788fdb95a8e530 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 20 Nov 2025 14:01:14 +0100 Subject: [PATCH 5/5] sdk: Added implementations for sending/receiving off-/on-chain funds --- libs/gl-plugin/src/node/mod.rs | 2 + libs/gl-sdk/.tasks.yml | 5 +- libs/gl-sdk/src/lib.rs | 3 + libs/gl-sdk/src/node.rs | 183 +++++++++++++++++++++++++++++---- libs/gl-sdk/src/signer.rs | 11 +- 5 files changed, 175 insertions(+), 29 deletions(-) diff --git a/libs/gl-plugin/src/node/mod.rs b/libs/gl-plugin/src/node/mod.rs index 9547f38a6..cb8728c8e 100644 --- a/libs/gl-plugin/src/node/mod.rs +++ b/libs/gl-plugin/src/node/mod.rs @@ -34,6 +34,7 @@ static LIMITER: OnceCell> = static RPC_CLIENT: OnceCell>> = OnceCell::const_new(); static RPC_POLL_INTERVAL: Duration = Duration::from_millis(500); +#[allow(unused)] const OPT_SUPPORTS_LSPS: usize = 729; pub async fn get_rpc>(path: P) -> Arc> { @@ -616,6 +617,7 @@ use cln_grpc::pb::node_server::NodeServer; #[derive(Clone, Debug)] struct Lsps2Offer { node_id: String, + #[allow(unused)] params: Vec, } diff --git a/libs/gl-sdk/.tasks.yml b/libs/gl-sdk/.tasks.yml index 49a614759..71a8e053b 100644 --- a/libs/gl-sdk/.tasks.yml +++ b/libs/gl-sdk/.tasks.yml @@ -76,7 +76,6 @@ tasks: cmds: - task: build-release - task: bindings-python - - uv run python build.py - uv build install-python: @@ -84,6 +83,7 @@ tasks: dir: "{{.ROOT_DIR}}/libs/gl-sdk" cmds: - task: package-python + - uv sync - uv pip install -e . prepare-test: @@ -91,8 +91,7 @@ tasks: dir: "{{.ROOT_DIR}}/libs/gl-sdk" cmds: - task: bindings-python - - uv run python build.py - + - task: install-python test: desc: "Run gl-sdk tests (loads library from source)" dir: "{{.ROOT_DIR}}/libs/gl-sdk" diff --git a/libs/gl-sdk/src/lib.rs b/libs/gl-sdk/src/lib.rs index 6d0f766a0..1e9aba787 100644 --- a/libs/gl-sdk/src/lib.rs +++ b/libs/gl-sdk/src/lib.rs @@ -16,6 +16,9 @@ pub enum Error { #[error("Error calling the rpc: {0}")] Rpc(String), + + #[error("Invalid argument: {0}={1}")] + Argument(String, String), #[error("Generic error: {0}")] Other(String), diff --git a/libs/gl-sdk/src/node.rs b/libs/gl-sdk/src/node.rs index 45721bc32..e44a8ef2d 100644 --- a/libs/gl-sdk/src/node.rs +++ b/libs/gl-sdk/src/node.rs @@ -35,6 +35,7 @@ impl Node { }) } + /// Stop the node if it is currently running. pub fn stop(&self) -> Result<(), Error> { let mut cln_client = exec(self.get_cln_client())?.clone(); @@ -43,7 +44,7 @@ impl Node { // It's ok, the error here is expected and should just be // telling us that we've lost the connection. This is to // be expected on shutdown, so we clamp this to success. - exec(cln_client.stop(req)); + let _ = exec(cln_client.stop(req)); Ok(()) } @@ -78,18 +79,95 @@ impl Node { Ok(ReceiveResponse { bolt11: res.bolt11 }) } - fn onchain_send(&self, req: &OnchainSendRequest) -> Result { - unimplemented!() + fn send(&self, invoice: String, amount_msat: Option) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + let req = clnpb::PayRequest { + amount_msat: match amount_msat { + Some(a) => Some(clnpb::Amount { msat: a }), + None => None, + }, + + bolt11: invoice, + description: None, + exclude: vec![], + exemptfee: None, + label: None, + localinvreqid: None, + maxdelay: None, + maxfee: None, + maxfeepercent: None, + partial_msat: None, + retry_for: None, + riskfactor: None, + }; + exec(cln_client.pay(req)) + .map_err(|e| Error::Rpc(e.to_string())) + .map(|r| r.into_inner().into()) } - fn onchain_receive( + + fn onchain_send( &self, - addresstype: Option, - ) -> Result { - unimplemented!() + destination: String, + amount_or_all: String, + ) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + // Decode what the user intends to do. Either we have `all`, + // or we have an amount that we can parse. + let (num, suffix): (String, String) = amount_or_all.chars().partition(|c| c.is_digit(10)); + + let num = if num.len() > 0 { + num.parse::().unwrap() + } else { + 0 + }; + let satoshi = match (num, suffix.as_ref()) { + (n, "") | (n, "sat") => clnpb::AmountOrAll { + // No value suffix, interpret as satoshis. This is an + // onchain RPC method, hence the sat denomination by + // default. + value: Some(clnpb::amount_or_all::Value::Amount(clnpb::Amount { + msat: n * 1000, + })), + }, + (n, "msat") => clnpb::AmountOrAll { + // No value suffix, interpret as satoshis. This is an + // onchain RPC method, hence the sat denomination by + // default. + value: Some(clnpb::amount_or_all::Value::Amount(clnpb::Amount { + msat: n * 1000, + })), + }, + (0, "all") => clnpb::AmountOrAll { + value: Some(clnpb::amount_or_all::Value::All(true)), + }, + (_, _) => return Err(Error::Argument("amount_or_all".to_owned(), amount_or_all)), + }; + + let req = clnpb::WithdrawRequest { + destination: destination, + minconf: None, + feerate: None, + satoshi: Some(satoshi), + utxos: vec![], + }; + + exec(cln_client.withdraw(req)) + .map_err(|e| Error::Rpc(e.to_string())) + .map(|r| r.into_inner().into()) } - fn send(&self, invoice: String) -> SendResponse { - unimplemented!() + fn onchain_receive(&self) -> Result { + let mut cln_client = exec(self.get_cln_client())?.clone(); + + let req = clnpb::NewaddrRequest { + addresstype: Some(clnpb::newaddr_request::NewaddrAddresstype::All.into()), + }; + + let res = exec(cln_client.new_addr(req)) + .map_err(|e| Error::Rpc(e.to_string()))? + .into_inner(); + Ok(res.into()) } } @@ -113,31 +191,92 @@ impl Node { } } +#[allow(unused)] #[derive(uniffi::Object)] -struct OnchainSendResponse {} - -#[derive(uniffi::Object)] -struct OnchainSendRequest { - label: String, - description: String, - amount_msat: Option, +struct OnchainSendResponse { + tx: Vec, + txid: Vec, + psbt: String, } -#[derive(uniffi::Enum)] -enum AddressType { - BECH32, - P2TR, +impl From for OnchainSendResponse { + fn from(other: clnpb::WithdrawResponse) -> Self { + Self { + tx: other.tx, + txid: other.txid, + psbt: other.psbt, + } + } } +#[allow(unused)] #[derive(uniffi::Object)] struct OnchainReceiveResponse { - address: String, + bech32: String, + p2tr: String, +} + +impl From for OnchainReceiveResponse { + fn from(other: clnpb::NewaddrResponse) -> Self { + OnchainReceiveResponse { + bech32: other.bech32.unwrap_or_default(), + p2tr: other.p2tr.unwrap_or_default(), + } + } } +#[allow(unused)] #[derive(uniffi::Object)] -struct SendResponse {} +struct SendResponse { + status: PayStatus, + preimage: Vec, + amount_msat: u64, + amount_sent_msat: u64, + parts: u32, +} + +impl From for SendResponse { + fn from(other: clnpb::PayResponse) -> Self { + Self { + status: other.status.into(), + preimage: other.payment_preimage, + amount_msat: other.amount_msat.unwrap().msat, + amount_sent_msat: other.amount_sent_msat.unwrap().msat, + parts: other.parts, + } + } +} +#[allow(unused)] #[derive(uniffi::Object)] struct ReceiveResponse { bolt11: String, } + +#[derive(uniffi::Enum)] +enum PayStatus { + COMPLETE = 0, + PENDING = 1, + FAILED = 2, +} + +impl From for PayStatus { + fn from(other: clnpb::pay_response::PayStatus) -> Self { + match other { + clnpb::pay_response::PayStatus::Complete => PayStatus::COMPLETE, + clnpb::pay_response::PayStatus::Failed => PayStatus::FAILED, + clnpb::pay_response::PayStatus::Pending => PayStatus::PENDING, + } + } +} + +impl From for PayStatus { + fn from(i: i32) -> Self { + match i { + 0 => PayStatus::COMPLETE, + 1 => PayStatus::PENDING, + 2 => PayStatus::FAILED, + o => panic!("Unknown pay_status {}", o), + } + } +} diff --git a/libs/gl-sdk/src/signer.rs b/libs/gl-sdk/src/signer.rs index 70e7d6ceb..8b683e453 100644 --- a/libs/gl-sdk/src/signer.rs +++ b/libs/gl-sdk/src/signer.rs @@ -1,5 +1,5 @@ use crate::{Credentials, Error}; -use bip39::{Language, Mnemonic}; +use bip39::Mnemonic; use std::str::FromStr; #[derive(uniffi::Object, Clone)] @@ -13,7 +13,7 @@ pub struct Signer { impl Signer { #[uniffi::constructor()] fn new(phrase: String) -> Result { - let phrase = Mnemonic::from_str(phrase.as_str()).map_err(|e| Error::PhraseCorrupted())?; + let phrase = Mnemonic::from_str(phrase.as_str()).map_err(|_e| Error::PhraseCorrupted())?; let seed = phrase.to_seed_normalized(&"").to_vec(); // FIXME: We may need to give the signer real credentials to @@ -52,7 +52,7 @@ impl Signer { } fn start(&self) -> Result { - let (mut tx, mut rx) = tokio::sync::mpsc::channel(1); + let (tx, rx) = tokio::sync::mpsc::channel(1); let clone = self.clone(); tokio::spawn(async move { @@ -70,7 +70,10 @@ impl Signer { // Not exported through uniffi, internal logic only. impl Signer { async fn run(&self, signal: tokio::sync::mpsc::Receiver<()>) { - self.inner.run_forever(signal).await.expect("Error running signer loop"); + self.inner + .run_forever(signal) + .await + .expect("Error running signer loop"); } }