{"id":24554952,"url":"https://github.com/conduition/lndlite","last_synced_at":"2026-02-10T11:36:25.228Z","repository":{"id":271167279,"uuid":"912591412","full_name":"conduition/lndlite","owner":"conduition","description":"Another LND API wrapper, now with 50% less syntactic sugar!","archived":false,"fork":false,"pushed_at":"2025-01-06T01:48:35.000Z","size":101,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-28T05:00:17.422Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/conduition.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-06T01:37:03.000Z","updated_at":"2025-01-06T01:48:38.000Z","dependencies_parsed_at":"2025-01-06T01:47:19.525Z","dependency_job_id":"e07bf5ea-e906-431b-ab8f-7308c58bafd4","html_url":"https://github.com/conduition/lndlite","commit_stats":null,"previous_names":["conduition/lndlite"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conduition%2Flndlite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conduition%2Flndlite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conduition%2Flndlite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conduition%2Flndlite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/conduition","download_url":"https://codeload.github.com/conduition/lndlite/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243902290,"owners_count":20366259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-23T03:37:22.667Z","updated_at":"2026-02-10T11:36:20.208Z","avatar_url":"https://github.com/conduition.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lndlite\n\n_Another LND wrapper, now with 50% less syntactic sugar!_\n\n- Access the [Lightning Network Daemon (LND) REST API](https://lightning.engineering/api-docs/api/lnd/rest-endpoints/) using `hyper` under the hood.\n- Fully async\n- Supports streamed responses for subscription endpoints\n- Pass in a custom HTTP connector interface\n- Bring Your Own Types\n- Avoid tight coupling\n\n\n## Example\n\nFirst, [download and install `lnd`](https://github.com/lightningnetwork/lnd).\n\n```console\ncurl -L https://github.com/lightningnetwork/lnd/releases/download/v0.18.4-beta/lnd-linux-amd64-v0.18.4-beta.tar.gz |\n  sudo tar -C /usr/local/bin -xz --strip-components=1\n```\n\nRun LND in regtest mode with no backend (just for example).\n\n```console\nlnd --bitcoin.regtest --bitcoin.node=nochainbackend --lnddir=/tmp/test --restlisten=127.0.0.1:8555\n```\n\nNow you can install and use `lndlite` in your crate. You'll need an async runtime like [`tokio`](https://tokio.rs). Here is an example program which uses `lndlite` (also in [`examples/simple.rs`](./examples/simple.rs)).\n\n```rust\nuse lndlite::{base64::Base64, serde, LndRestClient};\nuse sha2::{Digest as _, Sha256};\n\n#[derive(serde::Serialize)]\nstruct InitWalletRequest {\n    wallet_password: Base64\u003cString\u003e,\n    extended_master_key: String,\n}\n\n#[derive(serde::Deserialize)]\nstruct InitWalletResponse {\n    admin_macaroon: Base64\u003cVec\u003cu8\u003e\u003e,\n}\n\n#[derive(serde::Deserialize)]\nstruct StateUpdate {\n    state: String,\n}\n\n#[derive(serde::Serialize)]\nstruct AddInvoiceRequest {\n    value: u64,\n    r_preimage: Base64\u003c[u8; 32]\u003e,\n}\n\n#[derive(serde::Deserialize)]\nstruct AddInvoiceResponse {\n    r_hash: Base64\u003c[u8; 32]\u003e,\n    payment_request: String,\n}\n\n/// could use a cipherseed mnemonic instead\nconst XPRIV: \u0026str = concat!(\n    \"tprv8ZgxMBicQKsPdpgo44ctecZXcupSdNCZL5gmLS6FiUzrjqePmp7\",\n    \"KSSdJcCJ2z2w7aAh1poJBEQcLXi82KzeSg2tBZRvwwUynFrux1NUSuBa\",\n);\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let tls_cert_pem = std::fs::read(\"/tmp/test/tls.cert\")?;\n    let mut lnd_client =\n        LndRestClient::new_with_self_signed_cert(\"127.0.0.1:8555\".to_string(), b\"\", \u0026tls_cert_pem)?;\n\n    let InitWalletResponse {\n        admin_macaroon: Base64(macaroon),\n    } = lnd_client\n        .post(\n            \"/v1/initwallet\",\n            InitWalletRequest {\n                wallet_password: Base64(\"password123\".to_string()),\n                extended_master_key: XPRIV.to_string(),\n            },\n        )\n        .await?;\n\n    // We can now access API endpoints protected by macaroon authentication\n    lnd_client.set_macaroon(\u0026macaroon);\n    println!(\"wallet unlocked, macaroon: {:?}\", macaroon);\n\n    let mut state_stream = lnd_client.get_streamed(\"/v1/state/subscribe\").await?;\n\n    tokio::time::timeout(std::time::Duration::from_secs(10), async move {\n        while let Some(update) = state_stream.next::\u003cStateUpdate\u003e().await? {\n            println!(\"LND is in state: {}\", update.state);\n            if update.state == \"SERVER_ACTIVE\" {\n                return Ok(());\n            }\n        }\n        Ok::\u003c(), lndlite::RequestError\u003e(())\n    })\n    .await??;\n\n    println!(\"LND API server is fully active and ready for use\");\n\n    let preimage = [0x01u8; 32];\n\n    let AddInvoiceResponse {\n        r_hash: Base64(r_hash),\n        payment_request,\n    } = lnd_client\n        .post(\n            \"/v1/invoices\",\n            AddInvoiceRequest {\n                value: 10_000,\n                r_preimage: Base64(preimage),\n            },\n        )\n        .await?;\n\n    let hashed_preimage: [u8; 32] = Sha256::digest(\u0026preimage).into();\n    assert_eq!(r_hash, hashed_preimage);\n    println!(\"generated BOLT11 invoice: {}\", payment_request);\n\n    Ok(())\n}\n```\n\n```\n$ cargo run --example simple\n   Compiling lndlite v0.1.0\n    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.21s\n     Running `target/debug/examples/simple`\nwallet unlocked, macaroon: [2, 1, 3, 108, 110, 100, 2, 248, 1, 3, 10, 16, 249, 30, 150, 172, 176, 209, 254, 188, 250, 170, 230, 46, 193, 235, 59, 4, 18, 1, 48, 26, 22, 10, 7, 97, 100, 100, 114, 101, 115, 115, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 19, 10, 4, 105, 110, 102, 111, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 23, 10, 8, 105, 110, 118, 111, 105, 99, 101, 115, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 33, 10, 8, 109, 97, 99, 97, 114, 111, 111, 110, 18, 8, 103, 101, 110, 101, 114, 97, 116, 101, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 22, 10, 7, 109, 101, 115, 115, 97, 103, 101, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 23, 10, 8, 111, 102, 102, 99, 104, 97, 105, 110, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 22, 10, 7, 111, 110, 99, 104, 97, 105, 110, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 20, 10, 5, 112, 101, 101, 114, 115, 18, 4, 114, 101, 97, 100, 18, 5, 119, 114, 105, 116, 101, 26, 24, 10, 6, 115, 105, 103, 110, 101, 114, 18, 8, 103, 101, 110, 101, 114, 97, 116, 101, 18, 4, 114, 101, 97, 100, 0, 0, 6, 32, 213, 90, 160, 144, 226, 203, 1, 45, 247, 66, 85, 163, 243, 169, 44, 65, 44, 64, 240, 83, 71, 239, 236, 214, 187, 155, 244, 64, 63, 17, 198, 231]\nLND is in state: NON_EXISTING\nLND is in state: UNLOCKED\nLND is in state: RPC_ACTIVE\nLND is in state: SERVER_ACTIVE\nLND API server is fully active and ready for use\ngenerated BOLT11 invoice: lnbcrt100u1pnhkt4spp5wtxkappzcsrlkmgfs6g0zyct0hkhashh7hsaxz7e65slq9fkx7fsdqqcqzzsxqyz5vqsp5r5l0cs58vwaslfxx9che9kjm3udgpjsws9267t7mmj9jh4fy07gq9qxpqysgqxkelqfmpclv2uvfa34wh6rxdu08d9zhd73u3wvges2f238qy7w49wrmgymcdffj4z7hr8jy4qk6zn0evdlp95w4xwdwtlvsmnjcdc9gp22auz6\n```\n\n## Feature Flags\n\n| Flag | Description | Enabled by Default |\n|:-:|:-:|:-:|\n| `base64` | Adds the `base64` module with utilities for base64 encoding (commonly needed to interact with the LND REST API). | Yes |\n| `https` | Pulls in the `openssl` crate to handle HTTPS connection authentication with LND's TLS certificates, which are typically self-signed. | Yes |\n\n## Where are all the types/methods?\n\nThis crate is a **thin** wrapper to encourage correct async usage of the LND REST API with minimal dependencies. Unlike other LND API wrappers, this crate intentionally does not declare or maintain Rust methods and typedefs for the numerous endpoints and data structures available on the [LND API](https://lightning.engineering/api-docs/api/lnd/).\n\nThis crate does not pull in any cryptographic primitives or Bitcoin protocol code: It is solely an HTTP(S) API wrapper. We bundle only `hyper` for HTTP, `openssl` for TLS, and basic encoding/decoding utilities for UTF8 JSON, such as `serde_json` and `utf8-read` to handle newline-delimited JSON streams.\n\nUsers of this crate must declare their own types and then invoke REST API endpoints properly by referencing [the current documentation](https://lightning.engineering/api-docs/api/lnd/rest-endpoints/). This crate is simply a robust REST interface through which one can interact with a running LND server.\n\nThe philosophy behind this design is rooted in practical maintenance concerns: It's infeasible for me, a solo developer working in my free time, to keep a library's typedefs up to date with the vast API surface area of LND, with its full-time team of developers, let alone document it all properly.\n\nMost developers who use the LND API only need a few select methods from the dozens of endpoints available. And so instead this crate aims to make this use case possible without the need for constant attentive maintenance. As LND improves and its API changes, as new endpoints are added and old ones are deprecated, I want this crate to remain an evergreen resource for devs who rely on LND.\n\n\n## Can I use `rustls` instead of `openssl`?\n\nNot safely. `rustls` is so strictly adherent to the TLS specification that it does not accept the self-signed end-entity certificates generated by LND's default configuration.\n\n- https://github.com/lightningnetwork/lnd/issues/5450\n- https://github.com/rustls/rustls/issues/124\n\nIt is theoretically possible to implement the [`ServerCertVerifier`](https://docs.rs/rustls/0.23.20/rustls/client/danger/trait.ServerCertVerifier.html) trait and manually allow the LND self-signed cert. You would then use [`ClientConfig::dangerous`](https://docs.rs/rustls/0.23.20/rustls/client/struct.ClientConfig.html#method.dangerous) to create a [`hyper_rustls::HttpsConnector`](https://docs.rs/hyper-rustls/latest/hyper_rustls/struct.HttpsConnector.html) (using [`HttpsConnectorBuilder::with_tls_config`](https://docs.rs/hyper-rustls/latest/hyper_rustls/struct.HttpsConnectorBuilder.html#method.with_tls_config)), and finally pass this connector into `lndlite::LndRestClient::new_with_connector`.\n\nBut as you can see, this would involve modifying internal implementations of `rustls` which is far too unsafe for a production-grade library.\n\nThe \"correct\" fix is for LND to generate a separate TLS CA certificate, and then use it to sign end-entity certificates which are presented to REST/gRPC clients. However this requires action upstream in LND. Once [this issue](https://github.com/lightningnetwork/lnd/issues/5450) is resolved, please open an issue or a PR in this repo to add `rustls` support.\n\nA second workaround option is for an end-user to generate their own certificate authority (CA) and use it to sign a new certificate, which they can feed to LND. Simply place the end-entity certificate in `~/.lnd/tls.cert` (or wherever your LND data dir is), and restart LND. It will find and use this certificate. This setup follows the TLS specifications, and so a `hyper_rustls::HttpsConnector` should work if passed into `LndRestClient::new_with_connector`, as long as the CA is configured correctly in the `rustls::ClientConfig`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconduition%2Flndlite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconduition%2Flndlite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconduition%2Flndlite/lists"}