Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,222 changes: 776 additions & 446 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ members = [
"libs/gl-signerproxy",
"libs/gl-cli",
"libs/gl-util",
"libs/gl-sdk",
"libs/uniffi-bindgen",
]

[workspace.dependencies]
Expand Down
5 changes: 5 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ includes:
taskfile: "libs/gl-signerproxy/.tasks.yml"
dir: "."

sdk:
taskfile: "libs/gl-sdk/.tasks.yml"
dir: "."

tasks:
ci-check:
deps:
- ci-build
cmds:
- task: sdk:test
- task: clientpy:check
- task: testing:check
- task: clnvm:check
Expand Down
52 changes: 52 additions & 0 deletions libs/gl-client/.kacl.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions libs/gl-client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
24 changes: 19 additions & 5 deletions libs/gl-client/src/utils.rs
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -25,7 +25,21 @@ pub fn get_node_id_from_tls_config(tls_config: &TlsConfig) -> Result<Vec<u8>> {

let split_subject_common_name = subject_common_name.split("/").collect::<Vec<&str>>();

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"))
}
// 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
)
})
}
2 changes: 2 additions & 0 deletions libs/gl-plugin/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static LIMITER: OnceCell<RateLimiter<NotKeyed, InMemoryState, MonotonicClock>> =
static RPC_CLIENT: OnceCell<Arc<Mutex<cln_rpc::ClnRpc>>> = 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<P: AsRef<Path>>(path: P) -> Arc<Mutex<cln_rpc::ClnRpc>> {
Expand Down Expand Up @@ -616,6 +617,7 @@ use cln_grpc::pb::node_server::NodeServer;
#[derive(Clone, Debug)]
struct Lsps2Offer {
node_id: String,
#[allow(unused)]
params: Vec<crate::responses::OpeningFeeParams>,
}

Expand Down
6 changes: 3 additions & 3 deletions libs/gl-plugin/src/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,10 @@ impl From<crate::pb::LspInvoiceRequest> 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 {
Expand Down
111 changes: 111 additions & 0 deletions libs/gl-sdk/.tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
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 build

install-python:
desc: "Install Python package in development mode"
dir: "{{.ROOT_DIR}}/libs/gl-sdk"
cmds:
- task: package-python
- uv sync
- 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
- task: install-python
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
85 changes: 85 additions & 0 deletions libs/gl-sdk/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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 <test_name>
```

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
19 changes: 19 additions & 0 deletions libs/gl-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" ] }
Loading
Loading