diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 083ac61..6867e71 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -9,29 +9,3 @@ updates:
directory: "/"
schedule:
interval: "weekly"
- - package-ecosystem: "cargo"
- directory: "/"
- schedule:
- interval: "weekly"
- day: "monday"
- time: "06:00"
- timezone: "UTC"
-
- groups:
- all-dependencies:
- patterns:
- - "*"
-
- cooldown:
- default-days: 7
-
- open-pull-requests-limit: 1
-
- versioning-strategy: "auto"
-
- labels:
- - "dependencies"
- - "rust"
-
- allow:
- - dependency-type: "all"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3b0ca26..44922b0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,12 +17,6 @@ on:
tagged-release:
required: true
type: boolean
- python-version-1:
- required: true
- type: string
- python-version-2:
- required: true
- type: string
jobs:
build:
@@ -30,25 +24,27 @@ jobs:
strategy:
fail-fast: false
matrix:
- bitcoind-version: ["31.0"]
+ bitcoind-version: ["30.2"]
experimental: [1]
deprecated: [0]
- python-version: [ "${{ inputs.python-version-1 }}", "${{ inputs.python-version-2 }}"]
+ python-version: ["3.9", "3.14"]
os: ["ubuntu-latest"]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
- uses: actions/checkout@v7
+ uses: actions/checkout@v6
- name: Create cache paths
run: |
- sudo mkdir -p /usr/local/libexec/c-lightning/plugins
+ sudo mkdir /usr/local/libexec
+ sudo mkdir /usr/local/libexec/c-lightning
+ sudo mkdir /usr/local/libexec/c-lightning/plugins
sudo chown -R $USER /usr/local/libexec
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v7
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
@@ -64,7 +60,7 @@ jobs:
- name: Restore CLN cache
id: cache-cln
- uses: actions/cache/restore@v6
+ uses: actions/cache/restore@v5
with:
path: |
/usr/local/bin/lightning*
@@ -73,7 +69,7 @@ jobs:
- name: Restore bitcoind cache
id: cache-bitcoind
- uses: actions/cache/restore@v6
+ uses: actions/cache/restore@v5
with:
path: /usr/local/bin/bitcoin*
key: cache-bitcoind-${{ matrix.bitcoind-version }}-${{ steps.exact_versions.outputs.os_version }}
@@ -97,7 +93,7 @@ jobs:
- name: Save bitcoind cache
id: save-cache-bitcoind
if : ${{ success() && steps.cache-bitcoind.outputs.cache-hit != 'true'}}
- uses: actions/cache/save@v6
+ uses: actions/cache/save@v5
with:
path: /usr/local/bin/bitcoin*
key: ${{ steps.cache-bitcoind.outputs.cache-primary-key }}
@@ -115,7 +111,7 @@ jobs:
- name: Save CLN cache
id: save-cache-cln
if : ${{ success() && steps.cache-cln.outputs.cache-hit != 'true' }}
- uses: actions/cache/save@v6
+ uses: actions/cache/save@v5
with:
path: |
/usr/local/bin/lightning*
@@ -123,21 +119,25 @@ jobs:
key: ${{ steps.cache-cln.outputs.cache-primary-key }}
- name: Set up Rust
- if: ${{ inputs.tagged-release == false }}
+ if: ${{ inputs.tagged-release == false}}
uses: dtolnay/rust-toolchain@stable
+ - name: Set up protoc
+ if: ${{ inputs.tagged-release == false}}
+ uses: arduino/setup-protoc@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
- name: Install cargo-binstall
- if: ${{ inputs.tagged-release == false }}
+ if: ${{ inputs.tagged-release == false}}
uses: taiki-e/install-action@cargo-binstall
- name: Install cargo-msrv
- if: ${{ inputs.tagged-release == false }}
- env:
- GITHUB_TOKEN: ${{ github.token }}
+ if: ${{ inputs.tagged-release == false}}
run: cargo binstall --no-confirm cargo-msrv
- name: Verify MSRV
- if: ${{ inputs.tagged-release == false }}
+ if: ${{ inputs.tagged-release == false}}
run: cargo msrv verify
- name: Get plugin binary
@@ -151,13 +151,6 @@ jobs:
uv run python -m grpc_tools.protoc --proto_path="proto" --python_out="tests" --grpc_python_out="tests" proto/*.proto
fi
- url=$(curl -f --retry 3 --retry-delay 3 -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/BoltzExchange/hold/releases/latest \
- | jq '.assets[] | select(.name | endswith("linux-amd64.tar.gz")) | .browser_download_url' \
- | tr -d '\"')
- wget $url
- tar -xvf ${url##*/} -C tests
- mv "tests/build/hold-linux-amd64" "tests/hold"
-
cargo build
cargo test
fi
diff --git a/.github/workflows/latest_v25.02.yml b/.github/workflows/latest_v25.02.yml
new file mode 100644
index 0000000..6d8590c
--- /dev/null
+++ b/.github/workflows/latest_v25.02.yml
@@ -0,0 +1,14 @@
+name: Latest release on CLN v25.02.x
+
+on:
+ release:
+ types: [published, edited]
+ workflow_dispatch:
+
+jobs:
+ call-ci:
+ uses: ./.github/workflows/ci.yml
+ with:
+ cln-version: "v25.02.1"
+ pyln-version: "25.2.1"
+ tagged-release: true
\ No newline at end of file
diff --git a/.github/workflows/latest_v25.05.yml b/.github/workflows/latest_v25.05.yml
new file mode 100644
index 0000000..b5502c9
--- /dev/null
+++ b/.github/workflows/latest_v25.05.yml
@@ -0,0 +1,14 @@
+name: Latest release on CLN v25.05.x
+
+on:
+ release:
+ types: [published, edited]
+ workflow_dispatch:
+
+jobs:
+ call-ci:
+ uses: ./.github/workflows/ci.yml
+ with:
+ cln-version: "v25.05"
+ pyln-version: "25.5"
+ tagged-release: true
\ No newline at end of file
diff --git a/.github/workflows/latest_v25.09.yml b/.github/workflows/latest_v25.09.yml
index d96d48d..2926b68 100644
--- a/.github/workflows/latest_v25.09.yml
+++ b/.github/workflows/latest_v25.09.yml
@@ -9,8 +9,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v25.09.3"
- pyln-version: "25.9.3"
+ cln-version: "v25.09.2"
+ pyln-version: "25.9.2"
tagged-release: true
- python-version-1: "3.10"
- python-version-2: "3.12"
diff --git a/.github/workflows/latest_v25.12.yml b/.github/workflows/latest_v25.12.yml
index 3a86b18..268f5f6 100644
--- a/.github/workflows/latest_v25.12.yml
+++ b/.github/workflows/latest_v25.12.yml
@@ -9,8 +9,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v25.12.1"
- pyln-version: "25.12.1"
- tagged-release: true
- python-version-1: "3.10"
- python-version-2: "3.12"
+ cln-version: "v25.12"
+ pyln-version: "25.12"
+ tagged-release: true
\ No newline at end of file
diff --git a/.github/workflows/latest_v26.04.yml b/.github/workflows/latest_v26.04.yml
deleted file mode 100644
index a0dc3a0..0000000
--- a/.github/workflows/latest_v26.04.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: Latest release on CLN v26.04.x
-
-on:
- release:
- types: [published, edited]
- workflow_dispatch:
-
-jobs:
- call-ci:
- uses: ./.github/workflows/ci.yml
- with:
- cln-version: "v26.04"
- pyln-version: "26.4"
- tagged-release: true
- python-version-1: "3.10"
- python-version-2: "3.12"
diff --git a/.github/workflows/latest_v26.06.yml b/.github/workflows/latest_v26.06.yml
deleted file mode 100644
index 27edc2d..0000000
--- a/.github/workflows/latest_v26.06.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: Latest release on CLN v26.06.x
-
-on:
- release:
- types: [published, edited]
- workflow_dispatch:
-
-jobs:
- call-ci:
- uses: ./.github/workflows/ci.yml
- with:
- cln-version: "v26.06.6"
- pyln-version: "26.6.6"
- tagged-release: true
- python-version-1: "3.10"
- python-version-2: "3.14"
diff --git a/.github/workflows/master_v26.04.yml b/.github/workflows/master_v25.02.yml
similarity index 70%
rename from .github/workflows/master_v26.04.yml
rename to .github/workflows/master_v25.02.yml
index 82715be..e7b060f 100644
--- a/.github/workflows/master_v26.04.yml
+++ b/.github/workflows/master_v25.02.yml
@@ -1,4 +1,4 @@
-name: master on CLN v26.04.x
+name: master on CLN v25.02.x
on:
push:
@@ -19,8 +19,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v26.04"
- pyln-version: "26.4"
+ cln-version: "v25.02.1"
+ pyln-version: "25.2.1"
tagged-release: false
- python-version-1: "3.10"
- python-version-2: "3.12"
diff --git a/.github/workflows/master_v26.06.yml b/.github/workflows/master_v25.05.yml
similarity index 70%
rename from .github/workflows/master_v26.06.yml
rename to .github/workflows/master_v25.05.yml
index 25fe3a8..dfd753c 100644
--- a/.github/workflows/master_v26.06.yml
+++ b/.github/workflows/master_v25.05.yml
@@ -1,4 +1,4 @@
-name: master on CLN v26.06.x
+name: master on CLN v25.05.x
on:
push:
@@ -19,8 +19,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v26.06.6"
- pyln-version: "26.6.6"
+ cln-version: "v25.05"
+ pyln-version: "25.5"
tagged-release: false
- python-version-1: "3.10"
- python-version-2: "3.14"
diff --git a/.github/workflows/master_v25.09.yml b/.github/workflows/master_v25.09.yml
index 1a73ecd..7b62c39 100644
--- a/.github/workflows/master_v25.09.yml
+++ b/.github/workflows/master_v25.09.yml
@@ -19,8 +19,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v25.09.3"
- pyln-version: "25.9.3"
+ cln-version: "v25.09.2"
+ pyln-version: "25.9.2"
tagged-release: false
- python-version-1: "3.10"
- python-version-2: "3.12"
diff --git a/.github/workflows/master_v25.12.yml b/.github/workflows/master_v25.12.yml
index 7e0ae62..5df85d3 100644
--- a/.github/workflows/master_v25.12.yml
+++ b/.github/workflows/master_v25.12.yml
@@ -19,8 +19,6 @@ jobs:
call-ci:
uses: ./.github/workflows/ci.yml
with:
- cln-version: "v25.12.1"
- pyln-version: "25.12.1"
+ cln-version: "v25.12"
+ pyln-version: "25.12"
tagged-release: false
- python-version-1: "3.10"
- python-version-2: "3.12"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 39f2ae2..56b76c8 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,7 +13,7 @@ jobs:
rust-version: ${{ steps.versions.outputs.rust-version }}
steps:
- name: Checkout code
- uses: actions/checkout@v7
+ uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
@@ -25,6 +25,12 @@ jobs:
sudo apt update
sudo apt install -y gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf
+ - name: Install Protoc
+ uses: arduino/setup-protoc@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ version: "21.12"
+
- name: Build Linux binaries (release)
run: |
cargo build --profile optimized --locked --target x86_64-unknown-linux-gnu
@@ -57,13 +63,19 @@ jobs:
macos-deployment-target: ${{ steps.build.outputs.macos-deployment-target }}
steps:
- name: Checkout code
- uses: actions/checkout@v7
+ uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-apple-darwin, aarch64-apple-darwin
+ - name: Install Protoc
+ uses: arduino/setup-protoc@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ version: "21.12"
+
- name: Build macOS universal (release)
id: build
env:
@@ -135,7 +147,7 @@ jobs:
id: tag_name
run: echo "current_version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
- name: Checkout code
- uses: actions/checkout@v7
+ uses: actions/checkout@v6
- name: Get Changelog Entry
id: changelog_reader
uses: mindsers/changelog-reader-action@v2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e77df0d..2cb0208 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,35 +1,5 @@
# Changelog
-## [0.2.0] 2026-08-09
-
-### Added
-- holdinvoice methods: ``make_hold_invoice``, ``cancel_hold_invoice``, ``settle_hold_invoice``
-- holdinvoice notification: ``hold_invoice_accepted``
-
-### Changed
-- there are now five default relays that will be used if ``nip47-relays`` is not set
-- `pay_keysend` will use the new CLN `xkeysend` command using CLN v26.06+
-- Budget is updated on demand instead of by a background task
-- `list_transactions` is bounded (at most 500 transactions and ~128kB response) to prevent DoS
-- Upgrade ``nostr_sdk`` and CLN dependencies
-
-### Removed
-- ``multi_pay_invoice`` and ``multi_pay_keysend``, they were removed from the spec
-
-### Fixed
-- ``nip47-create`` no longer fails if the NWC fails to start, the error is only logged, since the NWC at that point is already persisted to the DB
-- Paying amount-less invoices with a request amount
-- Legacy keysend TLV byte decoding
-- Report the correct error when the payment route is too expensive
-- Notifications are sent per client, so one failing client no longer prevents the others from receiving them
-- Available payment methods are now determined from the node's RPC instead of it's (custom) version string
-- Deduplication of request events instead of filtering unreliably
-
-## [0.1.9] 2026-04-23
-
-### Fixed
-- ``nip47-budget``: race condition where new budget settings would sometimes be ignored
-
## [0.1.8] 2026-04-03
### Changed
diff --git a/Cargo.lock b/Cargo.lock
index a6393f7..3da29df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -25,41 +25,30 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.1.5"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
-version = "1.0.104"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arrayvec"
-version = "0.7.8"
+version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
-
-[[package]]
-name = "async-trait"
-version = "0.1.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 3.0.3",
-]
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "async-utility"
-version = "0.3.2"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "188f83b9a198af8c336e505611edb00d6d2ac5c694241c5a4f9a12316938cfe9"
+checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151"
dependencies = [
"futures-util",
"gloo-timers",
@@ -69,37 +58,37 @@ dependencies = [
[[package]]
name = "async-wsocket"
-version = "0.17.0"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c713e1f14c7b82e32ea159af1c6e2f070cfadbdf23fb2512acce9af0a26f1a2"
+checksum = "1c92385c7c8b3eb2de1b78aeca225212e4c9a69a78b802832759b108681a5069"
dependencies = [
+ "async-utility",
"futures",
"futures-util",
"js-sys",
"tokio",
- "tokio-happy-eyeballs",
"tokio-rustls",
"tokio-socks",
"tokio-tungstenite",
"url",
"wasm-bindgen",
- "wasm-bindgen-futures",
"web-sys",
]
[[package]]
-name = "atomic-waker"
-version = "1.1.2"
+name = "atomic-destructor"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4"
[[package]]
name = "base58ck"
-version = "0.1.101"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0"
+checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
dependencies = [
- "bitcoin_hashes 0.14.101",
+ "bitcoin-internals",
+ "bitcoin_hashes",
]
[[package]]
@@ -108,110 +97,88 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "base64ct"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
+
[[package]]
name = "bech32"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f"
-[[package]]
-name = "bech32"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbd3e1070bbdf4cd88a75264e18e8a26f7cb5c6949eadf0ceb85fb159cf08f8"
-
[[package]]
name = "bip39"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc"
dependencies = [
- "bitcoin_hashes 0.14.101",
+ "bitcoin_hashes",
"serde",
"unicode-normalization",
]
[[package]]
name = "bitcoin"
-version = "0.32.102"
+version = "0.32.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0ce8bd5baaa0d303a19915a6d93afed161f528654e42da2a7a97d05c59499a"
+checksum = "1e499f9fc0407f50fe98af744ab44fa67d409f76b6772e1689ec8485eb0c0f66"
dependencies = [
"base58ck",
- "bech32 0.11.1",
+ "bech32",
+ "bitcoin-internals",
"bitcoin-io",
"bitcoin-units",
- "bitcoin_hashes 0.14.101",
- "hex-conservative 0.2.2",
+ "bitcoin_hashes",
+ "hex-conservative",
"hex_lit",
- "secp256k1 0.29.1",
- "serde",
-]
-
-[[package]]
-name = "bitcoin-consensus-encoding"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "207311705279250ba465076a1bac4b1ac982855fff73fc5f67e22158ac58cdc9"
-dependencies = [
- "bitcoin-internals",
- "hex-conservative 1.2.0",
+ "secp256k1",
"serde",
]
[[package]]
name = "bitcoin-internals"
-version = "0.6.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5"
+checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
+dependencies = [
+ "serde",
+]
[[package]]
name = "bitcoin-io"
-version = "0.1.101"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78"
-dependencies = [
- "bitcoin-consensus-encoding",
-]
+checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953"
[[package]]
name = "bitcoin-units"
-version = "0.1.101"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51"
+checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2"
dependencies = [
- "bitcoin-consensus-encoding",
+ "bitcoin-internals",
"serde",
]
[[package]]
name = "bitcoin_hashes"
-version = "0.14.101"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2"
+checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b"
dependencies = [
"bitcoin-io",
- "hex-conservative 0.2.2",
- "serde",
-]
-
-[[package]]
-name = "bitcoin_hashes"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5304e53726dbe5f93141535e102ed97b5bf4714fbecefdda8f9fb98d7fdaff0e"
-dependencies = [
- "bitcoin-consensus-encoding",
- "bitcoin-internals",
- "hex-conservative 1.2.0",
+ "hex-conservative",
"serde",
]
[[package]]
name = "bitflags"
-version = "2.13.1"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]]
name = "block-buffer"
@@ -233,21 +200,15 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.20.3"
+version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
-
-[[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "bytes"
-version = "1.12.1"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cbc"
@@ -260,9 +221,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.4.2"
+version = "1.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e"
+checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -311,35 +272,28 @@ dependencies = [
[[package]]
name = "cln-nip47"
-version = "0.2.0"
+version = "0.1.8"
dependencies = [
"anyhow",
"cln-plugin",
"cln-rpc",
- "futures",
"hex",
"log",
"log-panics",
- "nostr",
"nostr-sdk",
"parking_lot",
- "prost",
- "protoc-bin-vendored",
"regex",
"serde",
"serde_json",
"tokio",
- "tonic",
- "tonic-prost",
- "tonic-prost-build",
"uuid",
]
[[package]]
name = "cln-plugin"
-version = "0.7.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9a4bb9c7335040d49c51900305b91155303539e9f54839bb194e915277bf882"
+checksum = "c340e01d74b553f761dd5636b8238cb92cacdf7d9d27a8820dad42da76ce0cb5"
dependencies = [
"anyhow",
"bytes",
@@ -356,9 +310,9 @@ dependencies = [
[[package]]
name = "cln-rpc"
-version = "0.7.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d9f5e26f0a2713ea1393eb3117c148295fa4c5f7db529713b20323ca7cc37aa"
+checksum = "d8c63eb175d58f0212e35e427237cf3e4f856f47ec7b8ad95110484d292fc819"
dependencies = [
"anyhow",
"bitcoin",
@@ -388,14 +342,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
+ "rand_core 0.6.4",
"typenum",
]
[[package]]
name = "data-encoding"
-version = "2.11.1"
+version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
+checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
[[package]]
name = "digest"
@@ -405,24 +360,25 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
+ "subtle",
]
[[package]]
name = "displaydoc"
-version = "0.2.7"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn",
]
[[package]]
name = "either"
-version = "1.17.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "equivalent"
@@ -430,49 +386,11 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-[[package]]
-name = "errno"
-version = "0.3.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
-dependencies = [
- "libc",
- "windows-sys 0.61.2",
-]
-
-[[package]]
-name = "faster-hex"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73"
-dependencies = [
- "heapless",
- "serde",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
-
[[package]]
name = "find-msvc-tools"
-version = "0.1.10"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
-
-[[package]]
-name = "fixedbitset"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "foldhash"
@@ -491,9 +409,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218"
+checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
"futures-channel",
"futures-core",
@@ -506,9 +424,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
"futures-sink",
@@ -516,15 +434,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-executor"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458"
+checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
"futures-core",
"futures-task",
@@ -533,38 +451,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
+checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
name = "futures-macro"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
+checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
]
[[package]]
name = "futures-sink"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
+checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
-version = "0.3.33"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-channel",
"futures-core",
@@ -594,8 +512,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
+ "js-sys",
"libc",
"wasi",
+ "wasm-bindgen",
]
[[package]]
@@ -612,14 +532,15 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.4.3"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
"r-efi 6.0.0",
- "rand_core 0.10.1",
+ "wasip2",
+ "wasip3",
]
[[package]]
@@ -634,34 +555,6 @@ dependencies = [
"wasm-bindgen",
]
-[[package]]
-name = "h2"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
-dependencies = [
- "atomic-waker",
- "bytes",
- "fnv",
- "futures-core",
- "futures-sink",
- "http",
- "indexmap",
- "slab",
- "tokio",
- "tokio-util",
- "tracing",
-]
-
-[[package]]
-name = "hash32"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
-dependencies = [
- "byteorder",
-]
-
[[package]]
name = "hashbrown"
version = "0.15.5"
@@ -673,19 +566,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.17.1"
+version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
-
-[[package]]
-name = "heapless"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
-dependencies = [
- "hash32",
- "stable_deref_trait",
-]
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "heck"
@@ -708,15 +591,6 @@ dependencies = [
"arrayvec",
]
-[[package]]
-name = "hex-conservative"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35431185f361ccf3ffc58254628af5f1f5d5f28531da2e02e5d6c82bbc282a10"
-dependencies = [
- "arrayvec",
-]
-
[[package]]
name = "hex_lit"
version = "0.1.1"
@@ -724,105 +598,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
[[package]]
-name = "http"
-version = "1.5.0"
+name = "hmac"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "http"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
"itoa",
]
-[[package]]
-name = "http-body"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c"
-dependencies = [
- "bytes",
- "http",
-]
-
-[[package]]
-name = "http-body-util"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2"
-dependencies = [
- "bytes",
- "futures-core",
- "http",
- "http-body",
- "pin-project-lite",
-]
-
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
-[[package]]
-name = "httpdate"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
-
-[[package]]
-name = "hyper"
-version = "1.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
-dependencies = [
- "atomic-waker",
- "bytes",
- "futures-channel",
- "futures-core",
- "h2",
- "http",
- "http-body",
- "httparse",
- "httpdate",
- "itoa",
- "pin-project-lite",
- "smallvec",
- "tokio",
- "want",
-]
-
-[[package]]
-name = "hyper-timeout"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
-dependencies = [
- "hyper",
- "hyper-util",
- "pin-project-lite",
- "tokio",
- "tower-service",
-]
-
-[[package]]
-name = "hyper-util"
-version = "0.1.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
-dependencies = [
- "bytes",
- "futures-channel",
- "futures-util",
- "http",
- "http-body",
- "hyper",
- "libc",
- "pin-project-lite",
- "socket2",
- "tokio",
- "tower-service",
- "tracing",
-]
-
[[package]]
name = "icu_collections"
version = "2.1.1"
@@ -904,6 +703,12 @@ dependencies = [
"zerovec",
]
+[[package]]
+name = "id-arena"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
[[package]]
name = "idna"
version = "1.1.0"
@@ -927,12 +732,14 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.14.0"
+version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff"
dependencies = [
"equivalent",
- "hashbrown 0.17.1",
+ "hashbrown 0.16.1",
+ "serde",
+ "serde_core",
]
[[package]]
@@ -946,12 +753,15 @@ dependencies = [
]
[[package]]
-name = "itertools"
-version = "0.14.0"
+name = "instant"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
- "either",
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
]
[[package]]
@@ -962,12 +772,13 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
-version = "0.3.104"
+version = "0.3.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
+checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
dependencies = [
"cfg-if",
"futures-util",
+ "once_cell",
"wasm-bindgen",
]
@@ -978,16 +789,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
-name = "libc"
-version = "0.2.189"
+name = "leb128fmt"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
-name = "linux-raw-sys"
-version = "0.12.1"
+name = "libc"
+version = "0.2.184"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
+checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
[[package]]
name = "litemap"
@@ -1006,9 +817,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.33"
+version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "log-panics"
@@ -1021,9 +832,9 @@ dependencies = [
[[package]]
name = "lru"
-version = "0.18.2"
+version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d2f2f9b4ba7e6b24d95e7e899329d35be83bcded72c8540cdd5368932d1d90a"
+checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
[[package]]
name = "matchers"
@@ -1036,27 +847,21 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.8.3"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "mio"
-version = "1.2.2"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
+checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
dependencies = [
"libc",
"wasi",
"windows-sys 0.61.2",
]
-[[package]]
-name = "multimap"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
-
[[package]]
name = "negentropy"
version = "0.5.0"
@@ -1065,71 +870,80 @@ checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d"
[[package]]
name = "nostr"
-version = "0.45.1"
+version = "0.44.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dde8c76076d334409d86c2e1db3e97abe5deb8cb92744f939cbc1fa45bd69e7"
+checksum = "3aa5e3b6a278ed061835fe1ee293b71641e6bf8b401cfe4e1834bbf4ef0a34e1"
dependencies = [
"aes",
"base64",
- "bech32 0.12.0",
+ "bech32",
"bip39",
- "bitcoin_hashes 1.2.0",
+ "bitcoin_hashes",
"cbc",
"chacha20",
"chacha20poly1305",
- "faster-hex",
- "opaquerr",
- "rand 0.10.2",
- "secp256k1 0.30.0",
+ "getrandom 0.2.17",
+ "hex",
+ "instant",
+ "scrypt",
+ "secp256k1",
"serde",
"serde_json",
"unicode-normalization",
- "universal-time",
"url",
- "zeroize",
]
[[package]]
name = "nostr-database"
-version = "0.45.1"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b1fdb9fcba732e32719662afad1b267e50322dbe89e506017ec13f24361bddf"
+checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1"
dependencies = [
+ "lru",
"nostr",
- "opaquerr",
+ "tokio",
]
[[package]]
name = "nostr-gossip"
-version = "0.45.0"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa07539e52a71cb91fe0d693facaa298f03fcf9edcd66a521094e18e286e2336"
+checksum = "ade30de16869618919c6b5efc8258f47b654a98b51541eb77f85e8ec5e3c83a6"
dependencies = [
"nostr",
- "opaquerr",
]
[[package]]
-name = "nostr-sdk"
-version = "0.45.1"
+name = "nostr-relay-pool"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26c86342f367bd9b173ec4a697e936e3a82d6dad5b4aa06c0d35d9b4f88a8e72"
+checksum = "4b1073ccfbaea5549fb914a9d52c68dab2aecda61535e5143dd73e95445a804b"
dependencies = [
"async-utility",
"async-wsocket",
- "faster-hex",
- "futures",
+ "atomic-destructor",
+ "hex",
"lru",
"negentropy",
"nostr",
"nostr-database",
- "nostr-gossip",
- "opaquerr",
- "rand 0.10.2",
"tokio",
- "tokio-stream",
"tracing",
- "universal-time",
+]
+
+[[package]]
+name = "nostr-sdk"
+version = "0.44.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "471732576710e779b64f04c55e3f8b5292f865fea228436daf19694f0bf70393"
+dependencies = [
+ "async-utility",
+ "nostr",
+ "nostr-database",
+ "nostr-gossip",
+ "nostr-relay-pool",
+ "tokio",
+ "tracing",
]
[[package]]
@@ -1153,12 +967,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
-[[package]]
-name = "opaquerr"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f933a4265d5cdad61d19bbdfc972ea5726d56cd8d3d57b8f2d3c365dd42bee9"
-
[[package]]
name = "parking_lot"
version = "0.12.5"
@@ -1182,43 +990,33 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "password-hash"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
+dependencies = [
+ "base64ct",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "pbkdf2"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
+dependencies = [
+ "digest",
+ "hmac",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-[[package]]
-name = "petgraph"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
-dependencies = [
- "fixedbitset",
- "hashbrown 0.15.5",
- "indexmap",
-]
-
-[[package]]
-name = "pin-project"
-version = "1.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"
-dependencies = [
- "pin-project-internal",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "1.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.119",
-]
-
[[package]]
name = "pin-project-lite"
version = "0.2.17"
@@ -1261,160 +1059,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn 2.0.119",
+ "syn",
]
[[package]]
name = "proc-macro2"
-version = "1.0.107"
+version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
-[[package]]
-name = "prost"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1"
-dependencies = [
- "bytes",
- "prost-derive",
-]
-
-[[package]]
-name = "prost-build"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042"
-dependencies = [
- "heck",
- "itertools",
- "log",
- "multimap",
- "petgraph",
- "prettyplease",
- "prost",
- "prost-types",
- "pulldown-cmark",
- "pulldown-cmark-to-cmark",
- "regex",
- "syn 2.0.119",
- "tempfile",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
-dependencies = [
- "anyhow",
- "itertools",
- "proc-macro2",
- "quote",
- "syn 2.0.119",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a"
-dependencies = [
- "prost",
-]
-
-[[package]]
-name = "protoc-bin-vendored"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1c381df33c98266b5f08186583660090a4ffa0889e76c7e9a5e175f645a67fa"
-dependencies = [
- "protoc-bin-vendored-linux-aarch_64",
- "protoc-bin-vendored-linux-ppcle_64",
- "protoc-bin-vendored-linux-s390_64",
- "protoc-bin-vendored-linux-x86_32",
- "protoc-bin-vendored-linux-x86_64",
- "protoc-bin-vendored-macos-aarch_64",
- "protoc-bin-vendored-macos-x86_64",
- "protoc-bin-vendored-win32",
-]
-
-[[package]]
-name = "protoc-bin-vendored-linux-aarch_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c350df4d49b5b9e3ca79f7e646fde2377b199e13cfa87320308397e1f37e1a4c"
-
-[[package]]
-name = "protoc-bin-vendored-linux-ppcle_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a55a63e6c7244f19b5c6393f025017eb5d793fd5467823a099740a7a4222440c"
-
-[[package]]
-name = "protoc-bin-vendored-linux-s390_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dba5565db4288e935d5330a07c264a4ee8e4a5b4a4e6f4e83fad824cc32f3b0"
-
-[[package]]
-name = "protoc-bin-vendored-linux-x86_32"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8854774b24ee28b7868cd71dccaae8e02a2365e67a4a87a6cd11ee6cdbdf9cf5"
-
-[[package]]
-name = "protoc-bin-vendored-linux-x86_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b38b07546580df720fa464ce124c4b03630a6fb83e05c336fea2a241df7e5d78"
-
-[[package]]
-name = "protoc-bin-vendored-macos-aarch_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89278a9926ce312e51f1d999fee8825d324d603213344a9a706daa009f1d8092"
-
-[[package]]
-name = "protoc-bin-vendored-macos-x86_64"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81745feda7ccfb9471d7a4de888f0652e806d5795b61480605d4943176299756"
-
-[[package]]
-name = "protoc-bin-vendored-win32"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95067976aca6421a523e491fce939a3e65249bac4b977adee0ee9771568e8aa3"
-
-[[package]]
-name = "pulldown-cmark"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e"
-dependencies = [
- "bitflags",
- "memchr",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark-to-cmark"
-version = "22.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90"
-dependencies = [
- "pulldown-cmark",
-]
-
[[package]]
name = "quote"
-version = "1.0.47"
+version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
@@ -1433,9 +1094,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
-version = "0.8.7"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -1444,24 +1105,14 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.5"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.5",
]
-[[package]]
-name = "rand"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
-dependencies = [
- "getrandom 0.4.3",
- "rand_core 0.10.1",
-]
-
[[package]]
name = "rand_chacha"
version = "0.3.1"
@@ -1500,12 +1151,6 @@ dependencies = [
"getrandom 0.3.4",
]
-[[package]]
-name = "rand_core"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
-
[[package]]
name = "redox_syscall"
version = "0.5.18"
@@ -1517,9 +1162,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.13.1"
+version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
@@ -1529,9 +1174,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.18"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
@@ -1540,9 +1185,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.11"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "ring"
@@ -1558,26 +1203,12 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "rustix"
-version = "1.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.61.2",
-]
-
[[package]]
name = "rustls"
-version = "0.23.43"
+version = "0.23.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
+checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
dependencies = [
- "log",
"once_cell",
"ring",
"rustls-pki-types",
@@ -1588,18 +1219,18 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.15.1"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
+checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
-version = "0.103.13"
+version = "0.103.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
+checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef"
dependencies = [
"ring",
"rustls-pki-types",
@@ -1608,9 +1239,18 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.23"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "salsa20"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
+dependencies = [
+ "cipher",
+]
[[package]]
name = "scopeguard"
@@ -1618,28 +1258,30 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "scrypt"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
+dependencies = [
+ "password-hash",
+ "pbkdf2",
+ "salsa20",
+ "sha2",
+]
+
[[package]]
name = "secp256k1"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
dependencies = [
- "bitcoin_hashes 0.14.101",
+ "bitcoin_hashes",
+ "rand 0.8.5",
"secp256k1-sys",
"serde",
]
-[[package]]
-name = "secp256k1"
-version = "0.30.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252"
-dependencies = [
- "bitcoin_hashes 0.14.101",
- "rand 0.8.7",
- "secp256k1-sys",
-]
-
[[package]]
name = "secp256k1-sys"
version = "0.10.1"
@@ -1650,10 +1292,16 @@ dependencies = [
]
[[package]]
-name = "serde"
-version = "1.0.229"
+name = "semver"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
@@ -1661,29 +1309,29 @@ dependencies = [
[[package]]
name = "serde_core"
-version = "1.0.229"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.229"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn",
]
[[package]]
name = "serde_json"
-version = "1.0.151"
+version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
@@ -1694,9 +1342,20 @@ dependencies = [
[[package]]
name = "sha1"
-version = "0.10.7"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1714,9 +1373,9 @@ dependencies = [
[[package]]
name = "shlex"
-version = "2.0.1"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
@@ -1726,15 +1385,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
-version = "1.15.2"
+version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "socket2"
-version = "0.6.5"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
+checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
dependencies = [
"libc",
"windows-sys 0.61.2",
@@ -1754,32 +1413,15 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.119"
+version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
-[[package]]
-name = "syn"
-version = "3.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "sync_wrapper"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
-
[[package]]
name = "synstructure"
version = "0.13.2"
@@ -1788,20 +1430,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.27.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
-dependencies = [
- "fastrand",
- "getrandom 0.4.3",
- "once_cell",
- "rustix",
- "windows-sys 0.61.2",
+ "syn",
]
[[package]]
@@ -1815,11 +1444,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.20"
+version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
- "thiserror-impl 2.0.20",
+ "thiserror-impl 2.0.18",
]
[[package]]
@@ -1830,25 +1459,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.20"
+version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn",
]
[[package]]
name = "thread_local"
-version = "1.1.10"
+version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
@@ -1865,9 +1494,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.12.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
+checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -1880,9 +1509,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.53.1"
+version = "1.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
+checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
dependencies = [
"bytes",
"libc",
@@ -1893,24 +1522,15 @@ dependencies = [
"windows-sys 0.61.2",
]
-[[package]]
-name = "tokio-happy-eyeballs"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8564c32dfb6f4257f8bc6edfc178a34af97520e0b7b9815500c55eb3d092f29f"
-dependencies = [
- "tokio",
-]
-
[[package]]
name = "tokio-macros"
-version = "2.7.2"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
+checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn",
]
[[package]]
@@ -1925,9 +1545,9 @@ dependencies = [
[[package]]
name = "tokio-socks"
-version = "0.5.3"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7e2948f60dbe26b35f2c7fb74ac2854c1fddded0fe9d7548fcc674a246f7615"
+checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
dependencies = [
"either",
"futures-util",
@@ -1937,21 +1557,20 @@ dependencies = [
[[package]]
name = "tokio-stream"
-version = "0.1.19"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
+checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
- "tokio-util",
]
[[package]]
name = "tokio-tungstenite"
-version = "0.28.0"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
+checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
dependencies = [
"futures-util",
"log",
@@ -1965,117 +1584,17 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.19"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
+checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
- "libc",
"pin-project-lite",
"tokio",
]
-[[package]]
-name = "tonic"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec"
-dependencies = [
- "async-trait",
- "base64",
- "bytes",
- "h2",
- "http",
- "http-body",
- "http-body-util",
- "hyper",
- "hyper-timeout",
- "hyper-util",
- "percent-encoding",
- "pin-project",
- "socket2",
- "sync_wrapper",
- "tokio",
- "tokio-rustls",
- "tokio-stream",
- "tower",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tonic-build"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734"
-dependencies = [
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn 2.0.119",
-]
-
-[[package]]
-name = "tonic-prost"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309"
-dependencies = [
- "bytes",
- "prost",
- "tonic",
-]
-
-[[package]]
-name = "tonic-prost-build"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a"
-dependencies = [
- "prettyplease",
- "proc-macro2",
- "prost-build",
- "prost-types",
- "quote",
- "syn 2.0.119",
- "tempfile",
- "tonic-build",
-]
-
-[[package]]
-name = "tower"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
-dependencies = [
- "futures-core",
- "futures-util",
- "indexmap",
- "pin-project-lite",
- "slab",
- "sync_wrapper",
- "tokio",
- "tokio-util",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tower-layer"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
-
-[[package]]
-name = "tower-service"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
-
[[package]]
name = "tracing"
version = "0.1.44"
@@ -2096,7 +1615,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
]
[[package]]
@@ -2138,42 +1657,30 @@ dependencies = [
"tracing-log",
]
-[[package]]
-name = "try-lock"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
-
[[package]]
name = "tungstenite"
-version = "0.28.0"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442"
+checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
dependencies = [
"bytes",
"data-encoding",
"http",
"httparse",
"log",
- "rand 0.9.5",
+ "rand 0.9.2",
"rustls",
"rustls-pki-types",
"sha1",
- "thiserror 2.0.20",
+ "thiserror 2.0.18",
"utf-8",
]
[[package]]
name = "typenum"
-version = "1.20.1"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
-
-[[package]]
-name = "unicase"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
@@ -2190,6 +1697,12 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -2200,12 +1713,6 @@ dependencies = [
"subtle",
]
-[[package]]
-name = "universal-time"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47a939edecc3c5a7b83c02e5f6b3c31d2bc69eabcc9a87ab12c6d37ee6dbc856"
-
[[package]]
name = "untrusted"
version = "0.9.0"
@@ -2239,11 +1746,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
-version = "1.24.0"
+version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
+checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9"
dependencies = [
- "getrandom 0.4.3",
+ "getrandom 0.4.2",
"js-sys",
"wasm-bindgen",
]
@@ -2260,15 +1767,6 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
-[[package]]
-name = "want"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
-dependencies = [
- "try-lock",
-]
-
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
@@ -2281,14 +1779,23 @@ version = "1.0.1+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
dependencies = [
- "wit-bindgen",
+ "wit-bindgen 0.46.0",
+]
+
+[[package]]
+name = "wasip3"
+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+dependencies = [
+ "wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-bindgen"
-version = "0.2.127"
+version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
+checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
dependencies = [
"cfg-if",
"once_cell",
@@ -2299,9 +1806,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.77"
+version = "0.4.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950"
+checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2309,9 +1816,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.127"
+version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
+checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2319,31 +1826,65 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.127"
+version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
+checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.127"
+version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
+checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
dependencies = [
"unicode-ident",
]
[[package]]
-name = "web-sys"
-version = "0.3.104"
+name = "wasm-encoder"
+version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30"
+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
+dependencies = [
+ "bitflags",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2355,14 +1896,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.9",
+ "webpki-roots 1.0.6",
]
[[package]]
name = "webpki-roots"
-version = "1.0.9"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
+checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
dependencies = [
"rustls-pki-types",
]
@@ -2461,6 +2002,94 @@ version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+dependencies = [
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
+]
+
[[package]]
name = "writeable"
version = "0.6.3"
@@ -2469,9 +2098,9 @@ checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
[[package]]
name = "yoke"
-version = "0.8.3"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5"
+checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
dependencies = [
"stable_deref_trait",
"yoke-derive",
@@ -2486,35 +2115,35 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
"synstructure",
]
[[package]]
name = "zerocopy"
-version = "0.8.56"
+version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
+checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.56"
+version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
+checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
]
[[package]]
name = "zerofrom"
-version = "0.1.8"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
+checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
dependencies = [
"zerofrom-derive",
]
@@ -2527,15 +2156,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
"synstructure",
]
[[package]]
name = "zeroize"
-version = "1.9.0"
+version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
+checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"
@@ -2567,11 +2196,11 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn",
]
[[package]]
name = "zmij"
-version = "1.0.23"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/Cargo.toml b/Cargo.toml
index a21e37a..f846dd5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cln-nip47"
-version = "0.2.0"
+version = "0.1.8"
edition = "2024"
rust-version = "1.85.0"
@@ -12,22 +12,14 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["fs", "sync", "rt-multi-thread"] }
-cln-rpc = "0.7"
+cln-rpc = "0.6"
# cln-rpc = { path = "../lightning/cln-rpc/", version = "^0.6" }
-cln-plugin = "0.7"
+cln-plugin = "0.6"
# cln-plugin = { path = "../lightning/plugins/", version = "^0.6" }
parking_lot = "0.12"
-# # nostr-sdk = { git = "https://github.com/rust-nostr/nostr.git", rev = "ff5be7d1416ea201887a02f648795010a3cbdf49" }
-# nostr = { git = "https://github.com/rust-nostr/nostr.git", rev = "ff5be7d1416ea201887a02f648795010a3cbdf49", features = [
-# "nip47",
-# "nip04",
-# "nip44",
-# ] }
-nostr = { version = "0.45.1", features = ["nip47", "nip04", "nip44"] }
-nostr-sdk = { version = "0.45.1" }
-
-futures = "0.3"
+# nostr-sdk = { git = "https://github.com/rust-nostr/nostr.git", rev = "f7122f5", features = ["nip47", "nip04", "nip44"]}
+nostr-sdk = { version = "0.44", features = ["nip47", "nip04", "nip44"] }
uuid = { version = "1", features = ["v4"] }
@@ -35,18 +27,6 @@ hex = "0.4"
regex = "1"
-tonic = { version = "0.14", default-features = false, features = [
- "codegen",
- "transport",
- "tls-ring",
-] }
-prost = "0.14"
-tonic-prost = "0.14"
-
-[build-dependencies]
-tonic-prost-build = "0.14"
-protoc-bin-vendored = "3"
-
[profile.optimized]
inherits = "release"
diff --git a/README.md b/README.md
index 5556fd0..8d8c56b 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,28 @@
# cln-nip47
-A core lightning plugin to connect wallets via Nostr Wallet Connect (NWC) as specified in [NIP-47](https://github.com/nostr-protocol/nips/blob/master/47.md). It is intended to be used by a single user, since all notifications got to all NWC's.
+A core lightning plugin to connect wallets via Nostr Wallet Connect (NWC) as specified in [NIP-47](https://github.com/nostr-protocol/nips/blob/master/47.md).
* [Installation](#installation)
* [Building](#building)
@@ -64,10 +64,11 @@ Release binaries for
* x86_64-linux
* armv7-linux (Raspberry Pi 32bit)
* aarch64-linux (Raspberry Pi 64bit)
-* universal-apple-darwin (macOS)
can be found on the [release](https://github.com/daywalker90/cln-nip47/releases) page. If you are unsure about your architecture you can run ``uname -m``.
+They require ``glibc>=2.31``, which you can check with ``ldd --version``.
+
# Building
You can build the plugin yourself instead of using the release binaries.
First clone the repo:
@@ -84,7 +85,7 @@ cargo build --release
After that the binary will be here: ``target/release/cln-nip47``
-Note: Release binaries are built with the ``optimized`` profile.
+Note: Release binaries are built using ``cross`` and the ``optimized`` profile.
# Documentation
@@ -97,12 +98,7 @@ It is highly recommended to use your own private relay since public relays may l
For a private relay you can for example use [nostr-rs-relay](https://github.com/scsibug/nostr-rs-relay) with ``pubkey_whitelist`` set to both ``clientkey_public`` and ``walletkey_public`` (returned from ``nip47-create``/``nip47-list``).
## Options
-* ``nip47-relays``: Specify the relays that you want to use with your NWC. Can be set multiple times to use multiple relays. NWC's you create will save these and even if you add or remove relays keep the relays from the moment you created that NWC. If you don't set this yourself these default relays will be used:
- * ``wss://nos.lol``
- * ``wss://relay.primal.net``
- * ``wss://relay.getalby.com/v1``
- * ``wss://relay.nostr.net``
- * ``wss://relay.snort.social``
+* ``nip47-relays``: Specify the relays that you want to use with your NWC. Can be set multiple times to use multiple relays. NWC's you create will save these and even if you add or remove relays keep the relays from the moment you created that NWC. You must set this atleast one time.
* ``nip47-notifications``: Enable/disable nip47 notifications. Default is enabled (``true``)
## Methods
@@ -131,25 +127,20 @@ For a private relay you can for example use [nostr-rs-relay](https://github.com/
* list all NWC configurations or just the one with ``label``
* ***label***: optional. The label the NWC was created with
-## Holdinvoice support
-For methods or notifications related to holdinvoices you need v0.3.2+ of [hold](https://github.com/BoltzExchange/hold) with enabled grpc (which is the default just make sure the port is free)
-
## Supported NWC methods
* ``pay_invoice``
+* ``multi_pay_invoice``
* ``pay_keysend`` (no ``preimage`` in request allowed since CLN only supports generating it itself)
+* ``multi_pay_keysend`` (no ``preimage`` in request allowed since CLN only supports generating it itself)
* ``make_invoice``
* ``lookup_invoice``
* ``list_transactions``
* ``get_balance``
* ``get_info`` (no ``block_hash``)
-* ``make_hold_invoice`` (requires [Holdinvoice support](#holdinvoice_support))
-* ``cancel_hold_invoice`` (requires [Holdinvoice support](#holdinvoice_support))
-* ``settle_hold_invoice`` (requires [Holdinvoice support](#holdinvoice_support))
## Supported NWC notifications
* ``payment_received``
* ``payment_sent``
-* ``hold_invoice_accepted`` (requires [Holdinvoice support](#holdinvoice_support))
## Supported content encryption:
* [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md)
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index 9b5fbd8..0000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Security Policy
-
-## Supported Versions
-
-Only the latest version is supported.
-
-## Reporting a Vulnerability
-
-To report security vulnerabilities, please send an email to:
-- `daywalker990@gmx.de`
-
-Note: This email address is exclusively for vulnerability reporting.
-
-For all other inquiries/communication, please use the Github issues.
-
-## Signatures For Releases
-
-The following keys may be used to communicate sensitive information to
-developers:
-
-| Name | Email | Fingerprint |
-|------|-------|-------------|
-| daywalker90 | `daywalker990@gmx.de` | 8A07 9421 A871 D0B1 0835 1193 7AB4 802E D5A6 39F3 |
-
-You can import a key by running the following command with that individual’s fingerprint:
-`gpg --keyserver hkps://keys.openpgp.org --recv-keys ""`.
-Ensure that you put quotes around fingerprints containing spaces.
diff --git a/build.rs b/build.rs
deleted file mode 100644
index 04c8cef..0000000
--- a/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-fn main() {
- let protoc = protoc_bin_vendored::protoc_bin_path().unwrap();
- unsafe { std::env::set_var("PROTOC", protoc) };
- tonic_prost_build::configure()
- .protoc_arg("--experimental_allow_proto3_optional")
- .compile_protos(&["protos/hold.proto"], &["protos"])
- .unwrap_or_else(|e| panic!("Could not build protos: {e}"));
-}
diff --git a/coffee.yml b/coffee.yml
index fa75d76..9c7d20d 100644
--- a/coffee.yml
+++ b/coffee.yml
@@ -1,6 +1,6 @@
plugin:
name: cln-nip47
- version: 0.2.0
+ version: 0.1.8
lang: rust
install: |
cargo build --release && cp target/release/cln-nip47 . && cargo clean
diff --git a/protos/hold.proto b/protos/hold.proto
deleted file mode 100644
index e7ad240..0000000
--- a/protos/hold.proto
+++ /dev/null
@@ -1,185 +0,0 @@
-syntax = "proto3";
-
-package hold;
-
-service Hold {
- rpc GetInfo (GetInfoRequest) returns (GetInfoResponse);
-
- rpc Invoice (InvoiceRequest) returns (InvoiceResponse) {}
- rpc Inject (InjectRequest) returns (InjectResponse) {}
-
- rpc List (ListRequest) returns (ListResponse) {}
-
- rpc Settle (SettleRequest) returns (SettleResponse) {}
- rpc Cancel (CancelRequest) returns (CancelResponse) {}
-
- // Cleans cancelled invoices
- rpc Clean (CleanRequest) returns (CleanResponse) {}
-
- rpc Track (TrackRequest) returns (stream TrackResponse) {}
- rpc TrackAll (TrackAllRequest) returns (stream TrackAllResponse) {}
-
- rpc OnionMessages (stream OnionMessageResponse) returns (stream OnionMessage) {}
-}
-
-enum HookAction {
- Continue = 0;
- Resolve = 1;
-}
-
-message GetInfoRequest {}
-message GetInfoResponse {
- string version = 1;
-}
-
-message Hop {
- bytes public_key = 1;
- uint64 short_channel_id = 2;
- uint64 base_fee = 3;
- uint64 ppm_fee = 4;
- uint64 cltv_expiry_delta = 5;
-}
-
-message RoutingHint {
- repeated Hop hops = 1;
-}
-
-message InvoiceRequest {
- bytes payment_hash = 1;
- uint64 amount_msat = 2;
-
- oneof description {
- string memo = 3;
- bytes hash = 4;
- }
-
- optional uint64 expiry = 5;
- optional uint64 min_final_cltv_expiry = 6;
- repeated RoutingHint routing_hints = 7;
-}
-message InvoiceResponse {
- string bolt11 = 1;
-}
-
-message InjectRequest {
- string invoice = 1;
- optional uint64 min_cltv_expiry = 2;
-}
-message InjectResponse {}
-
-message ListRequest {
- message Pagination {
- // Inclusive
- int64 index_start = 1;
- uint64 limit = 2;
- }
-
- oneof constraint {
- bytes payment_hash = 1;
- Pagination pagination = 2;
- }
-}
-
-enum InvoiceState {
- UNPAID = 0;
- ACCEPTED = 1;
- PAID = 2;
- CANCELLED = 3;
-}
-
-message Htlc {
- int64 id = 1;
- InvoiceState state = 2;
- string scid = 3;
- uint64 channel_id = 4;
- uint64 msat = 5;
- uint64 created_at = 6;
- optional uint64 cltv_expiry = 7;
-}
-
-message Invoice {
- int64 id = 1;
- bytes payment_hash = 2;
- optional bytes preimage = 3;
- string invoice = 4;
- InvoiceState state = 5;
- uint64 created_at = 6;
- optional uint64 settled_at = 8;
-
- repeated Htlc htlcs = 7;
-
- optional uint64 min_cltv_expiry = 9;
-}
-
-message ListResponse {
- repeated Invoice invoices = 1;
-}
-
-message SettleRequest {
- bytes payment_preimage = 1;
-}
-message SettleResponse {}
-
-message CancelRequest {
- bytes payment_hash = 1;
-}
-message CancelResponse {}
-
-message CleanRequest {
- // Clean everything older than age seconds
- optional uint64 age = 1;
-}
-message CleanResponse {
- uint64 cleaned = 1;
-}
-
-message TrackRequest {
- bytes payment_hash = 1;
-}
-
-message TrackResponse {
- InvoiceState state = 1;
-}
-
-message TrackAllRequest {
- repeated bytes payment_hashes = 1;
-}
-
-message TrackAllResponse {
- bytes payment_hash = 1;
- string bolt11 = 2;
- InvoiceState state = 3;
-}
-
-message OnionMessage {
- message ReplyBlindedPath {
- message Hop {
- optional bytes blinded_node_id = 1;
- optional bytes encrypted_recipient_data = 2;
- }
-
- optional bytes first_node_id = 1;
- optional string first_scid = 2;
- optional uint64 first_scid_dir = 3;
- optional bytes first_path_key = 4;
- repeated Hop hops = 5;
- }
-
- message UnknownField {
- uint64 number = 1;
- bytes value = 2;
- }
-
- uint64 id = 1;
- optional bytes pathsecret = 2;
- optional ReplyBlindedPath reply_blindedpath = 3;
- optional bytes invoice_request = 4;
- optional bytes invoice = 5;
- optional bytes invoice_error = 6;
- repeated UnknownField unknown_fields = 7;
-}
-
-message OnionMessageResponse {
- uint64 id = 1;
- HookAction action = 2;
-}
diff --git a/src/main.rs b/src/main.rs
index 1c3323a..778d840 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,4 @@
-use std::{
- path::{Path, PathBuf},
- str::FromStr,
- time::Duration,
-};
+use std::{path::Path, time::Duration};
use anyhow::anyhow;
use cln_plugin::{
@@ -10,29 +6,16 @@ use cln_plugin::{
Plugin,
options::{ConfigOption, DefaultBooleanConfigOption, StringArrayConfigOption},
};
-use cln_rpc::{
- ClnRpc,
- model::{
- requests::{DecodeRequest, ListdatastoreRequest},
- responses::DecodeType,
- },
-};
-use nostr::nips::nip47;
+use cln_rpc::{ClnRpc, model::requests::ListdatastoreRequest};
+use nostr_sdk::nips::nip47;
use nwc::run_nwc;
use nwc_notifications::{payment_received_handler, payment_sent_handler};
use parse::read_startup_options;
use rpc::{nwc_budget, nwc_create, nwc_list, nwc_revoke};
-use serde_json::json;
use structs::PluginState;
use tokio::time;
-use tonic::transport::{Certificate, ClientTlsConfig, Endpoint, Identity};
use util::{load_nwc_store, update_nwc_store};
-use crate::{
- hold::{InvoiceState, ListRequest, hold_client::HoldClient},
- nwc_notifications::holdinvoice_accepted_handler,
-};
-
mod nwc;
mod nwc_balance;
mod nwc_hold;
@@ -49,9 +32,6 @@ mod tasks;
mod util;
pub const STARTUP_DELAY: u64 = 1;
-pub mod hold {
- tonic::include_proto!("hold");
-}
const OPT_RELAYS: StringArrayConfigOption = ConfigOption::new_str_arr_no_default(
"nip47-relays",
@@ -63,33 +43,30 @@ const OPT_NOTIFICATIONS: DefaultBooleanConfigOption = ConfigOption::new_bool_wit
"Enable/disable nip47-notifications. Default is `true`",
);
pub const PLUGIN_NAME: &str = "cln-nip47";
-pub const WALLET_READ_OR_RECEIVE_METHODS: [nip47::Method; 5] = [
+pub const WALLET_READ_METHODS: [nip47::Method; 5] = [
nip47::Method::MakeInvoice,
nip47::Method::LookupInvoice,
nip47::Method::ListTransactions,
nip47::Method::GetBalance,
nip47::Method::GetInfo,
];
-pub const WALLET_PAY_METHODS: [nip47::Method; 2] =
- [nip47::Method::PayInvoice, nip47::Method::PayKeysend];
-pub const WALLET_HOLD_METHODS: [nip47::Method; 3] = [
- nip47::Method::MakeHoldInvoice,
- nip47::Method::CancelHoldInvoice,
- nip47::Method::SettleHoldInvoice,
+pub const WALLET_PAY_METHODS: [nip47::Method; 4] = [
+ nip47::Method::PayInvoice,
+ nip47::Method::MultiPayInvoice,
+ nip47::Method::PayKeysend,
+ nip47::Method::MultiPayKeysend,
];
pub const WALLET_NOTIFICATIONS: [nip47::NotificationType; 2] = [
nip47::NotificationType::PaymentReceived,
nip47::NotificationType::PaymentSent,
];
-pub const WALLET_HOLD_NOTIFICATIONS: [nip47::NotificationType; 1] =
- [nip47::NotificationType::HoldInvoiceAccepted];
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
unsafe {
std::env::set_var(
"CLN_PLUGIN_LOG",
- "cln_plugin=info,cln_rpc=info,cln_nip47=trace,info",
+ "cln_plugin=info,cln_rpc=info,cln_nip47=debug,info",
);
};
log_panics::init();
@@ -132,16 +109,6 @@ async fn main() -> Result<(), anyhow::Error> {
};
let plugin = confplugin.start(state).await?;
- match check_hold_support(plugin.clone()).await {
- Ok(()) => {
- log::info!("Hold support activated, loading pending invoices...");
- if let Err(e) = load_pending_hold_invoices(plugin.clone()).await {
- log::error!("Error loading pending hold invoices: {e}");
- }
- }
- Err(e) => log::info!("Hold support not activated: {e}"),
- }
-
{
let mut rpc = plugin.state().rpc_lock.lock().await;
@@ -163,16 +130,6 @@ async fn main() -> Result<(), anyhow::Error> {
}
}
- let plugin_clone_cleanup = plugin.clone();
- tokio::spawn(async move {
- loop {
- if let Err(e) = tasks::cleanup_event_ids(plugin_clone_cleanup.clone()).await {
- log::warn!("Error in cleanup_event_ids thread: {e}");
- }
- time::sleep(Duration::from_secs(10)).await;
- }
- });
-
plugin.join().await
}
@@ -181,8 +138,8 @@ async fn shutdown_handler(
_args: serde_json::Value,
) -> Result<(), anyhow::Error> {
let mut locked_handles = plugin.state().handles.lock().await;
- for (_x, wallet_service) in locked_handles.drain() {
- wallet_service.client.shutdown().await;
+ for (_x, (client, _client_pubkey)) in locked_handles.drain() {
+ client.shutdown().await;
}
std::process::exit(0)
}
@@ -206,186 +163,7 @@ async fn load_nwcs(plugin: Plugin, rpc: &mut ClnRpc) -> Result<(),
}
}
- // We don't keep track of inflight payments succeeding
- // while the plugin is dynamically restarted
- if nwc_store.reserved_msat != 0 {
- log::warn!(
- "Releasing {} msat leftover budget reservation for {label}",
- nwc_store.reserved_msat
- );
- nwc_store.reserved_msat = 0;
- update_nwc_store(rpc, label, nwc_store.clone()).await?;
- }
-
run_nwc(plugin.clone(), label.clone(), nwc_store.clone()).await?;
}
Ok(())
}
-
-async fn load_pending_hold_invoices(plugin: Plugin) -> Result<(), anyhow::Error> {
- let mut hold_client = plugin.state().hold_client.lock().clone().unwrap();
- let invoices_request = ListRequest { constraint: None };
- let invoices = hold_client
- .list(invoices_request)
- .await?
- .into_inner()
- .invoices;
-
- let mut rpc = plugin.state().rpc_lock.lock().await;
-
- for invoice in invoices {
- if invoice.state() == InvoiceState::Accepted || invoice.state() == InvoiceState::Unpaid {
- // Bound the accepted handler by the invoice's expiry. The hold
- // plugin has no expired state, so without this it would wait
- // forever on an invoice that expires while Unpaid.
- let invoice_decoded = rpc
- .call_typed(&DecodeRequest {
- string: invoice.invoice.clone(),
- })
- .await?;
-
- if !invoice_decoded.valid {
- log::warn!(
- "Skipping hold invoice {}, could not decode it",
- hex::encode(&invoice.payment_hash)
- );
- continue;
- }
-
- let (created_at, expiry) = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => (
- invoice_decoded.invoice_created_at,
- invoice_decoded.invoice_relative_expiry.map(u64::from),
- ),
- DecodeType::BOLT11_INVOICE => (invoice_decoded.created_at, invoice_decoded.expiry),
- _ => continue,
- };
-
- let (Some(created_at), Some(expiry)) = (created_at, expiry) else {
- log::warn!(
- "Skipping hold invoice {}: missing creation time or expiry",
- hex::encode(&invoice.payment_hash)
- );
- continue;
- };
- let expires_at = created_at.saturating_add(expiry);
-
- log::debug!(
- "Starting holdinvoice accepted handler for {}",
- hex::encode(&invoice.payment_hash)
- );
- tokio::spawn(holdinvoice_accepted_handler(
- plugin.clone(),
- invoice.payment_hash,
- expires_at,
- ));
- }
- }
-
- Ok(())
-}
-
-async fn check_hold_support(plugin: Plugin) -> Result<(), anyhow::Error> {
- let mut rpc = plugin.state().rpc_lock.lock().await;
- let hold_grpc_host_response: serde_json::Value = rpc
- .call_raw("listconfigs", &json!({"config": "hold-grpc-host"}))
- .await?;
-
- let Some(hold_grpc_host_configs) = hold_grpc_host_response.get("configs") else {
- return Err(anyhow!("Unsopprted listconfigs response!"));
- };
- let Some(hold_grpc_host_config) = hold_grpc_host_configs.get("hold-grpc-host") else {
- return Err(anyhow!("hold-grpc-host config not found"));
- };
- let Some(hold_grpc_host_value) = hold_grpc_host_config.get("value_str") else {
- return Err(anyhow!("hold-grpc-host config not a string"));
- };
- let Some(hold_grpc_host) = hold_grpc_host_value.as_str() else {
- return Err(anyhow!("hold-grpc-host config not convertable to string"));
- };
-
- let hold_grpc_port_response: serde_json::Value = rpc
- .call_raw("listconfigs", &json!({"config": "hold-grpc-port"}))
- .await?;
- let Some(hold_grpc_port_configs) = hold_grpc_port_response.get("configs") else {
- return Err(anyhow!("Unsopprted listconfigs response!"));
- };
- let Some(hold_grpc_port_config) = hold_grpc_port_configs.get("hold-grpc-port") else {
- return Err(anyhow!("hold-grpc-port config not found"));
- };
- let Some(hold_grpc_port_value) = hold_grpc_port_config.get("value_int") else {
- return Err(anyhow!("hold-grpc-port config not a number"));
- };
- let hold_grpc_port = if let Some(hgh) = hold_grpc_port_value.as_u64() {
- u16::try_from(hgh)?
- } else {
- return Err(anyhow!("hold-grpc-port config not convertable to integer"));
- };
-
- let cert_dir = PathBuf::from_str(&plugin.configuration().lightning_dir)?.join("hold");
-
- log::debug!(
- "Searching {} for hold plugin certs",
- cert_dir.to_str().unwrap()
- );
-
- let cert_max_retries = 10;
- let mut cert_retries = 0;
- while cert_retries < cert_max_retries && !do_certificates_exist(&cert_dir) {
- log::debug!("Hold certificates incomplete. Waiting...");
- time::sleep(Duration::from_millis(500)).await;
- cert_retries += 1;
- }
-
- let ca_cert = tokio::fs::read(cert_dir.join("ca.pem")).await?;
- let client_cert = tokio::fs::read(cert_dir.join("client.pem")).await?;
- let client_key = tokio::fs::read(cert_dir.join("client-key.pem")).await?;
-
- let identity = Identity::from_pem(client_cert, client_key);
-
- let ca = Certificate::from_pem(ca_cert);
-
- let tls_config = ClientTlsConfig::new()
- .ca_certificate(ca)
- .identity(identity)
- .domain_name("hold");
-
- let endpoint = Endpoint::from_shared(format!("https://{hold_grpc_host}:{hold_grpc_port}"))?
- .tls_config(tls_config)?
- .keep_alive_while_idle(true)
- .connect_timeout(Duration::from_secs(5));
-
- let chan_max_retries = 20;
- let mut chan_retries = 0;
-
- let channel = loop {
- match endpoint.connect().await {
- Ok(channel) => break channel,
- Err(e) if chan_retries < chan_max_retries => {
- chan_retries += 1;
-
- log::debug!(
- "Hold gRPC server not ready, retrying ({chan_retries}/{chan_max_retries}): {e}"
- );
-
- time::sleep(Duration::from_millis(500)).await;
- }
- Err(e) => {
- return Err(anyhow!("Hold gRPC server did not become ready: {e}"));
- }
- }
- };
-
- *plugin.state().hold_client.lock() = Some(HoldClient::new(channel));
-
- Ok(())
-}
-
-fn do_certificates_exist(cert_dir: &Path) -> bool {
- let required_files = ["client.pem", "client-key.pem", "ca.pem"];
-
- required_files.iter().all(|file| {
- let path = cert_dir.join(file);
- path.exists() && path.metadata().is_ok_and(|m| m.len() > 0)
- })
-}
diff --git a/src/nwc.rs b/src/nwc.rs
index dfd0e2c..448334b 100644
--- a/src/nwc.rs
+++ b/src/nwc.rs
@@ -1,24 +1,31 @@
-use std::time::Duration;
+use std::{borrow::Cow, time::Duration};
use anyhow::anyhow;
use cln_plugin::Plugin;
-use futures::StreamExt;
-use nostr::{
- event::{Event, EventBuilder, EventId, FinalizeEventAsync, Kind, Tag},
- filter::Filter,
- key::{Keys, PublicKey, SecretKey},
- nips::{nip04, nip44, nip47},
- types::Timestamp,
-};
use nostr_sdk::{
- client::{self, Client, ClientNotification},
- error::Error,
- relay::RelayStatus,
+ Alphabet,
+ Client,
+ Event,
+ EventBuilder,
+ EventId,
+ Keys,
+ PublicKey,
+ RelayPoolNotification,
+ RelayStatus,
+ SecretKey,
+ SignerError,
+ SingleLetterTag,
+ TagKind,
+ Timestamp,
+ client,
+ nips::{nip04, nip44, nip47},
+ nostr::{Filter, Kind, Tag},
};
-use tokio::time;
+use tokio::{sync::oneshot, time};
use crate::{
OPT_NOTIFICATIONS,
+ STARTUP_DELAY,
nwc_balance::get_balance_response,
nwc_hold::{
cancel_hold_invoice_response,
@@ -27,49 +34,50 @@ use crate::{
},
nwc_info::get_info_response,
nwc_invoice::make_invoice_response,
- nwc_keysend::pay_keysend_response,
+ nwc_keysend::{multi_pay_keysend, pay_keysend_response},
nwc_lookups::{list_transactions_response, lookup_invoice_response},
- nwc_pay::pay_invoice_response,
- structs::{ID_MAX_AGE, NwcStore, PluginState, WalletService},
- util::{build_capabilities, build_notifications_vec, is_read_only_nwc, save_event_id},
+ nwc_pay::{multi_pay_invoice, pay_invoice_response},
+ structs::{NwcStore, PluginState},
+ tasks::budget_task,
+ util::{build_capabilities, build_notifications_vec, is_read_only_nwc},
};
-#[allow(clippy::too_many_lines)]
pub async fn run_nwc(
plugin: Plugin,
label: String,
nwc_store: NwcStore,
-) -> Result<(), Error> {
+) -> Result<(), client::Error> {
let (method_capabilities, _) = build_capabilities(is_read_only_nwc(&nwc_store), &plugin);
- let wallet_keys = Keys::new(SecretKey::from_hex(&nwc_store.walletkey)?);
- let client_keys = Keys::new(nwc_store.uri.secret.clone());
+ let wallet_keys = Keys::new(
+ SecretKey::from_hex(&nwc_store.walletkey)
+ .map_err(|e| client::Error::Signer(SignerError::backend(e)))?,
+ );
+ let client_pubkey = Keys::new(nwc_store.uri.secret.clone()).public_key();
- let nostr_client = Client::new();
+ let client = Client::new(wallet_keys.clone());
log::debug!("relay_count:{}", nwc_store.uri.relays.len());
for relay in &nwc_store.uri.relays {
log::debug!("Adding relay: {relay}");
- nostr_client.add_relay(relay).await?;
+ client.add_relay(relay).await?;
}
if nwc_store.interval_config.is_some() {
- log::debug!("NWC {label} uses an interval budget");
+ start_nwc_budget_job(&plugin, label.clone());
}
- let nostr_client_clone = nostr_client.clone();
+ let client_clone = client.clone();
let plugin_clone = plugin.clone();
let label_clone = label.clone();
- let client_keys_clone = client_keys.clone();
- let wallet_keys_clone = wallet_keys.clone();
tokio::spawn(async move {
loop {
- nostr_client_clone
- .connect()
- .and_wait(Duration::from_secs(30))
+ client_clone.connect().await;
+ client_clone
+ .wait_for_connection(Duration::from_secs(30))
.await;
- let relays = nostr_client_clone.relays().await;
+ let relays = client_clone.relays().await;
if relays.is_empty() {
log::info!("No more relays left, we probably shut down. Exiting...");
break;
@@ -90,67 +98,62 @@ pub async fn run_nwc(
if let Err(e) = send_nwc_info_event(
plugin_clone.clone(),
- nostr_client_clone.clone(),
+ client_clone.clone(),
method_capabilities.clone(),
- wallet_keys_clone.clone(),
+ wallet_keys.clone(),
)
.await
{
log::warn!("{e}");
- nostr_client_clone.disconnect().await;
+ client_clone.disconnect().await;
time::sleep(Duration::from_secs(5)).await;
continue;
}
let filter = Filter::new()
.kind(Kind::WalletConnectRequest)
- .author(client_keys_clone.public_key());
+ .author(client_pubkey)
+ .since(Timestamp::now() - STARTUP_DELAY - 1);
- let mut notifications = nostr_client_clone.notifications();
-
- match nostr_client_clone.subscribe(filter).await {
- Ok(o) => {
- if o.success.is_empty() {
- log::warn!("Could not subscribe to any relay!");
- nostr_client_clone.disconnect().await;
- time::sleep(Duration::from_secs(5)).await;
- continue;
- }
- }
- Err(e) => {
- log::warn!("Error subscribing to relays: {e}");
- nostr_client_clone.disconnect().await;
- time::sleep(Duration::from_secs(5)).await;
- continue;
- }
+ if let Err(e) = client_clone.subscribe(filter, None).await {
+ log::warn!("Could not subscribe to nwc events! {e}");
+ client_clone.disconnect().await;
+ time::sleep(Duration::from_secs(5)).await;
+ continue;
}
- while let Some(notification) = notifications.next().await {
- if let Err(e) = nwc_request_handler(
- notification,
- &nostr_client_clone,
- &plugin_clone,
- &label_clone,
- &wallet_keys_clone,
- client_keys_clone.public_key(),
- )
+ let client_clone_handler = client_clone.clone();
+ match client_clone
+ .handle_notifications(|notification| {
+ let client_clone_handler = client_clone_handler.clone();
+ let plugin_clone = plugin_clone.clone();
+ let label_clone = label_clone.clone();
+ let wallet_keys_clone = wallet_keys.clone();
+ nwc_request_handler(
+ notification,
+ client_clone_handler,
+ plugin_clone,
+ label_clone,
+ wallet_keys_clone,
+ client_pubkey,
+ )
+ })
.await
- {
- log::warn!("NWC handler for `{label_clone}` had an error: {e}");
+ {
+ Ok(()) => {
+ log::info!("NWC handler for `{label_clone}` stopped");
+ break;
}
+ Err(e) => log::warn!("NWC handler for `{label_clone}` had an error: {e}"),
}
-
- {};
}
});
let mut locked_handles = plugin.state().handles.lock().await;
- let wallet_service = WalletService {
- client: nostr_client,
- client_pubkey: client_keys.public_key(),
- wallet_secret: wallet_keys,
- };
- locked_handles.insert(label.clone(), wallet_service);
+ locked_handles.insert(
+ label.clone(),
+ (client, Keys::new(nwc_store.uri.secret).public_key()),
+ );
Ok(())
}
@@ -173,7 +176,7 @@ pub async fn send_nwc_info_event(
.tag(Tag::parse(vec!["notifications", ¬ification_capabilities]).unwrap());
}
- let info_event = match info_event_builder.finalize_async(&wallet_keys).await {
+ let info_event = match info_event_builder.sign_with_keys(&wallet_keys) {
Ok(o) => o,
Err(e) => {
return Err(anyhow!("Could not sign info_event! {e}"));
@@ -201,103 +204,95 @@ pub async fn send_nwc_info_event(
pub async fn stop_nwc(plugin: Plugin, label: &String) {
let mut locked_handles = plugin.state().handles.lock().await;
- if let Some(wallet_service) = locked_handles.remove(label) {
- wallet_service.client.shutdown().await;
+ if let Some((client, _client_pubkey)) = locked_handles.remove(label) {
+ client.shutdown().await;
+ }
+
+ stop_nwc_budget_job(&plugin, label);
+}
+
+pub fn start_nwc_budget_job(plugin: &Plugin, label: String) {
+ let (tx, rx) = oneshot::channel::<()>();
+ tokio::spawn(budget_task(rx, plugin.clone(), label.clone()));
+ plugin.state().budget_jobs.lock().insert(label, tx);
+}
+
+pub fn stop_nwc_budget_job(plugin: &Plugin, label: &String) {
+ let mut budget_jobs = plugin.state().budget_jobs.lock();
+ let job = budget_jobs.remove(label);
+ if let Some(j) = job {
+ let _ = j.send(());
}
}
-#[allow(clippy::too_many_lines)]
async fn nwc_request_handler(
- notification: ClientNotification,
- nostr_client: &client::Client,
- plugin: &Plugin,
- label: &str,
- wallet_keys: &Keys,
+ notification: RelayPoolNotification,
+ client: client::Client,
+ plugin: Plugin,
+ label: String,
+ wallet_keys: Keys,
client_pubkey: PublicKey,
-) -> Result<(), Box> {
+) -> Result> {
let (relay_url, subscription_id, event) = match notification {
- ClientNotification::Event {
+ RelayPoolNotification::Event {
relay_url,
subscription_id,
event,
} => (relay_url, subscription_id, event),
- ClientNotification::Message {
+ RelayPoolNotification::Message {
relay_url: _,
message: _,
- }
- | ClientNotification::Shutdown => return Ok(()),
+ } => return Ok(false),
+ RelayPoolNotification::Shutdown => return Ok(true),
};
- log::trace!("relay_url:{relay_url} subscription_id:{subscription_id} {event:?}");
+ if let Some(expi) = event.tags.expiration() {
+ if *expi < Timestamp::now() {
+ return Ok(false);
+ }
+ }
+ log::debug!("relay_url:{relay_url} subscription_id:{subscription_id} {event:?}");
let mut use_nip44 = check_nip44_support(&event);
- let request = decrypt_request(&event.content, wallet_keys, &client_pubkey, &mut use_nip44)?;
+ let request = decrypt_request(&event.content, &wallet_keys, &client_pubkey, &mut use_nip44)?;
- let responses = if event.tags.expiration().is_some()
- && event.tags.expiration().unwrap() < Timestamp::now()
- {
- vec![(
- nip47::Response {
- result_type: request.method,
- error: Some(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Event expired".to_owned(),
- }),
- result: None,
- },
- None,
- )]
- } else if event.created_at.as_secs() < (Timestamp::now().as_secs() - ID_MAX_AGE) {
- vec![(
- nip47::Response {
- result_type: request.method,
- error: Some(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Event created too far in the past".to_owned(),
- }),
- result: None,
- },
- None,
- )]
- } else {
- {
- let mut rpc = plugin.state().rpc_lock.lock().await;
- save_event_id(&mut rpc, event.id.to_hex(), event.created_at).await?;
+ let responses = match request.params {
+ nip47::RequestParams::PayInvoice(pay_invoice_request) => {
+ pay_invoice_response(plugin.clone(), pay_invoice_request, &label).await
}
-
- match request.params {
- nip47::RequestParams::PayInvoice(pay_invoice_request) => {
- pay_invoice_response(plugin.clone(), pay_invoice_request, label).await
- }
- nip47::RequestParams::PayKeysend(pay_keysend_request) => {
- pay_keysend_response(plugin.clone(), pay_keysend_request, label).await
- }
- nip47::RequestParams::MakeInvoice(make_invoice_request) => {
- make_invoice_response(plugin.clone(), make_invoice_request).await
- }
- nip47::RequestParams::LookupInvoice(lookup_invoice_request) => {
- lookup_invoice_response(plugin.clone(), lookup_invoice_request).await
- }
- nip47::RequestParams::ListTransactions(list_transactions_request) => {
- list_transactions_response(plugin.clone(), list_transactions_request).await
- }
- nip47::RequestParams::GetBalance => get_balance_response(plugin.clone(), label).await,
- nip47::RequestParams::GetInfo => get_info_response(plugin.clone(), label).await,
- nip47::RequestParams::MakeHoldInvoice(make_hold_invoice_request) => {
- make_hold_invoice_response(plugin.clone(), make_hold_invoice_request).await
- }
- nip47::RequestParams::CancelHoldInvoice(cancel_hold_invoice_request) => {
- cancel_hold_invoice_response(plugin.clone(), cancel_hold_invoice_request).await
- }
- nip47::RequestParams::SettleHoldInvoice(settle_hold_invoice_request) => {
- settle_hold_invoice_response(plugin.clone(), settle_hold_invoice_request).await
- }
+ nip47::RequestParams::MultiPayInvoice(multi_pay_invoice_request) => {
+ multi_pay_invoice(plugin.clone(), multi_pay_invoice_request, &label).await
+ }
+ nip47::RequestParams::PayKeysend(pay_keysend_request) => {
+ pay_keysend_response(plugin, pay_keysend_request, &label).await
+ }
+ nip47::RequestParams::MultiPayKeysend(multi_pay_keysend_request) => {
+ multi_pay_keysend(plugin.clone(), multi_pay_keysend_request, &label).await
+ }
+ nip47::RequestParams::MakeInvoice(make_invoice_request) => {
+ make_invoice_response(plugin.clone(), make_invoice_request).await
+ }
+ nip47::RequestParams::LookupInvoice(lookup_invoice_request) => {
+ lookup_invoice_response(plugin.clone(), lookup_invoice_request).await
+ }
+ nip47::RequestParams::ListTransactions(list_transactions_request) => {
+ list_transactions_response(plugin.clone(), list_transactions_request).await
+ }
+ nip47::RequestParams::GetBalance => get_balance_response(plugin.clone(), &label).await,
+ nip47::RequestParams::GetInfo => get_info_response(plugin.clone(), &label).await,
+ nip47::RequestParams::MakeHoldInvoice(make_hold_invoice_request) => {
+ make_hold_invoice_response(plugin.clone(), make_hold_invoice_request, &label).await
+ }
+ nip47::RequestParams::CancelHoldInvoice(cancel_hold_invoice_request) => {
+ cancel_hold_invoice_response(plugin.clone(), cancel_hold_invoice_request, &label).await
+ }
+ nip47::RequestParams::SettleHoldInvoice(settle_hold_invoice_request) => {
+ settle_hold_invoice_response(plugin.clone(), settle_hold_invoice_request, &label).await
}
};
-
for (response, id) in responses {
let content =
- match encrypt_response_content(&response, wallet_keys, &client_pubkey, use_nip44) {
+ match encrypt_response_content(&response, &wallet_keys, &client_pubkey, use_nip44) {
Ok(o) => o,
Err(e) => {
log::warn!("{e}");
@@ -306,7 +301,7 @@ async fn nwc_request_handler(
};
let response_event =
- match build_response_event(event.id, content, wallet_keys, client_pubkey, id).await {
+ match build_response_event(event.id, content, &wallet_keys, client_pubkey, id) {
Ok(o) => o,
Err(e) => {
log::warn!("Error signing reponse event! {e}");
@@ -314,7 +309,7 @@ async fn nwc_request_handler(
}
};
- let send_result = match nostr_client.send_event(&response_event).await {
+ let send_result = match client.send_event(&response_event).await {
Ok(o) => o,
Err(e) => {
log::warn!("Error sending response event! {e}");
@@ -332,25 +327,20 @@ async fn nwc_request_handler(
);
continue;
}
- for success in send_result.success {
- log::trace!("Sent to {}", success.0);
- }
- for failure in send_result.failed {
- log::trace!("Failed to send to {}: {}", failure.0, failure.1);
- }
- log::trace!("SENT RESPONSE {response_event:?}");
+ log::debug!("SENT RESPONSE {response_event:?}");
}
- Ok(())
+ Ok(false)
}
fn check_nip44_support(event: &Event) -> bool {
- for tag in event.tags.iter() {
- if tag.kind() == "encryption" {
- if let Some(enc_tag_content) = tag.content() {
- if enc_tag_content.contains("nip44_v2") {
- return true;
- }
+ if let Some(encryption_tag) = event
+ .tags
+ .find(TagKind::Custom(Cow::Borrowed("encryption")))
+ {
+ if let Some(enc_tag_content) = encryption_tag.content() {
+ if enc_tag_content.contains("nip44_v2") {
+ return true;
}
}
}
@@ -398,7 +388,7 @@ fn decrypt_request(
}
}
};
- log::trace!("Decrypted (nip44_v2:{use_nip44}):{content}");
+ log::debug!("Decrypted (nip44_v2:{use_nip44}):{content}");
let request: nip47::Request = match serde_json::from_str(&content) {
Ok(o) => o,
Err(e) => {
@@ -421,7 +411,7 @@ fn encrypt_response_content(
return Err(anyhow!("Error serializing response! {e}"));
}
};
- log::trace!("RESPONSE:{response_str}");
+ log::debug!("RESPONSE:{response_str}");
if use_nip44 {
match nip44::encrypt(
wallet_keys.secret_key(),
@@ -440,7 +430,7 @@ fn encrypt_response_content(
}
}
-async fn build_response_event(
+fn build_response_event(
event_id: EventId,
content: String,
wallet_keys: &Keys,
@@ -451,9 +441,15 @@ async fn build_response_event(
.tag(Tag::event(event_id))
.tag(Tag::public_key(client_pubkey));
if let Some(i) = id {
- response_builder = response_builder.tag(Tag::identifier(i));
+ response_builder = response_builder.tag(Tag::custom(
+ TagKind::SingleLetter(SingleLetterTag {
+ character: Alphabet::D,
+ uppercase: false,
+ }),
+ vec![i],
+ ));
}
- match response_builder.finalize_async(wallet_keys).await {
+ match response_builder.sign_with_keys(wallet_keys) {
Ok(o) => Ok(o),
Err(e) => Err(e.into()),
}
diff --git a/src/nwc_balance.rs b/src/nwc_balance.rs
index 2fde546..c29b343 100644
--- a/src/nwc_balance.rs
+++ b/src/nwc_balance.rs
@@ -1,11 +1,8 @@
use cln_plugin::Plugin;
use cln_rpc::{model::requests::ListpeerchannelsRequest, primitives::ChannelState};
-use nostr::nips::nip47;
+use nostr_sdk::nips::nip47;
-use crate::{
- structs::PluginState,
- util::{get_budget_msat, load_nwc_store},
-};
+use crate::{structs::PluginState, util::load_nwc_store};
pub async fn get_balance_response(
plugin: Plugin,
@@ -43,7 +40,7 @@ async fn get_balance(
message: e.to_string(),
})?;
- let balance = if let Some(bdgt_amt) = get_budget_msat(&nwc_store) {
+ let balance = if let Some(bdgt_amt) = nwc_store.budget_msat {
bdgt_amt
} else {
let listpeerchannels = rpc
diff --git a/src/nwc_hold.rs b/src/nwc_hold.rs
index 4ce23a3..e048d0c 100644
--- a/src/nwc_hold.rs
+++ b/src/nwc_hold.rs
@@ -1,248 +1,58 @@
-use std::str::FromStr;
-
use cln_plugin::Plugin;
-use cln_rpc::primitives::Sha256;
-use nostr::{nips::nip47, types::Timestamp};
+use nostr_sdk::nips::nip47;
-use crate::{
- hold::{CancelRequest, InvoiceRequest, SettleRequest, invoice_request::Description},
- nwc_notifications::holdinvoice_accepted_handler,
- structs::PluginState,
-};
+use crate::structs::PluginState;
pub async fn make_hold_invoice_response(
- plugin: Plugin,
- params: nip47::MakeHoldInvoiceRequest,
+ _plugin: Plugin,
+ _params: nip47::MakeHoldInvoiceRequest,
+ _label: &str,
) -> Vec<(nip47::Response, Option)> {
- vec![match make_hold_invoice(plugin, params).await {
- Ok(o) => (
- nip47::Response {
- result_type: nip47::Method::MakeHoldInvoice,
- error: None,
- result: Some(nip47::ResponseResult::MakeHoldInvoice(o)),
- },
- None,
- ),
- Err(e) => (
- nip47::Response {
- result_type: nip47::Method::MakeHoldInvoice,
- error: Some(e),
- result: None,
- },
- None,
- ),
- }]
-}
-
-async fn make_hold_invoice(
- plugin: Plugin,
- params: nip47::MakeHoldInvoiceRequest,
-) -> Result {
- let Some(mut hold_client) = plugin.state().hold_client.lock().clone() else {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::NotImplemented,
- message: "No hold plugin found".to_owned(),
- });
- };
-
- let description: Option = if let Some(d_hash) = ¶ms.description_hash {
- if let Some(description) = ¶ms.description {
- let my_description_hash = Sha256::const_hash(description.as_bytes());
- let description_hash = Sha256::from_str(d_hash).map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?;
- if my_description_hash != description_hash {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "description_hash not matching description".to_owned(),
- });
- }
- }
-
- let desc_hash_bytes = match hex::decode(d_hash) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Could not convert description hash to bytes".to_owned(),
- });
- }
- };
- Some(Description::Hash(desc_hash_bytes))
- } else {
- params
- .description
- .as_ref()
- .map(|desc| Description::Memo(desc.clone()))
- };
-
- let payment_hash = match hex::decode(¶ms.payment_hash) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid payment hash".to_owned(),
- });
- }
- };
-
- let expiry = params.expiry.unwrap_or(60 * 60);
-
- let holdinvoice_request = InvoiceRequest {
- payment_hash: payment_hash.clone(),
- amount_msat: params.amount,
- expiry: Some(expiry),
- min_final_cltv_expiry: params.min_cltv_expiry_delta.map(u64::from),
- routing_hints: Vec::new(),
- description,
- };
-
- let holdinvoice = hold_client
- .invoice(holdinvoice_request)
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: format!("Error creating hold invoice: {e}"),
- })?
- .into_inner();
-
- let expires_at = Timestamp::now() + expiry;
-
- let response = nip47::MakeHoldInvoiceResponse {
- invoice: Some(holdinvoice.bolt11),
- transaction_type: nip47::TransactionType::Incoming,
- description: params.description,
- description_hash: params.description_hash,
- amount: params.amount,
- created_at: Timestamp::now(),
- expires_at,
- metadata: None,
- payment_hash: params.payment_hash,
- };
-
- tokio::spawn(holdinvoice_accepted_handler(
- plugin,
- payment_hash,
- expires_at.as_secs(),
- ));
- Ok(response)
+ vec![(
+ nip47::Response {
+ result_type: nip47::Method::MakeHoldInvoice,
+ error: Some(nip47::NIP47Error {
+ code: nip47::ErrorCode::NotImplemented,
+ message: "Not implemented".to_owned(),
+ }),
+ result: None,
+ },
+ None,
+ )]
}
pub async fn cancel_hold_invoice_response(
- plugin: Plugin,
- params: nip47::CancelHoldInvoiceRequest,
+ _plugin: Plugin,
+ _params: nip47::CancelHoldInvoiceRequest,
+ _label: &str,
) -> Vec<(nip47::Response, Option)> {
- vec![match cancel_hold_invoice(plugin, params).await {
- Ok(o) => (
- nip47::Response {
- result_type: nip47::Method::CancelHoldInvoice,
- error: None,
- result: Some(nip47::ResponseResult::CancelHoldInvoice(o)),
- },
- None,
- ),
- Err(e) => (
- nip47::Response {
- result_type: nip47::Method::CancelHoldInvoice,
- error: Some(e),
- result: None,
- },
- None,
- ),
- }]
-}
-
-async fn cancel_hold_invoice(
- plugin: Plugin,
- params: nip47::CancelHoldInvoiceRequest,
-) -> Result {
- let Some(mut hold_client) = plugin.state().hold_client.lock().clone() else {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::NotImplemented,
- message: "No hold plugin found".to_owned(),
- });
- };
-
- let payment_hash = match hex::decode(¶ms.payment_hash) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid payment hash".to_owned(),
- });
- }
- };
-
- let hold_cancel_request = CancelRequest { payment_hash };
-
- let hold_cancel_response = hold_client.cancel(hold_cancel_request).await;
-
- match hold_cancel_response {
- Ok(_o) => Ok(nip47::CancelHoldInvoiceResponse {}),
- Err(e) => Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- }),
- }
+ vec![(
+ nip47::Response {
+ result_type: nip47::Method::MakeHoldInvoice,
+ error: Some(nip47::NIP47Error {
+ code: nip47::ErrorCode::NotImplemented,
+ message: "Not implemented".to_owned(),
+ }),
+ result: None,
+ },
+ None,
+ )]
}
pub async fn settle_hold_invoice_response(
- plugin: Plugin,
- params: nip47::SettleHoldInvoiceRequest,
+ _plugin: Plugin,
+ _params: nip47::SettleHoldInvoiceRequest,
+ _label: &str,
) -> Vec<(nip47::Response, Option)> {
- vec![match settle_hold_invoice(plugin, params).await {
- Ok(o) => (
- nip47::Response {
- result_type: nip47::Method::SettleHoldInvoice,
- error: None,
- result: Some(nip47::ResponseResult::SettleHoldInvoice(o)),
- },
- None,
- ),
- Err(e) => (
- nip47::Response {
- result_type: nip47::Method::SettleHoldInvoice,
- error: Some(e),
- result: None,
- },
- None,
- ),
- }]
-}
-
-async fn settle_hold_invoice(
- plugin: Plugin,
- params: nip47::SettleHoldInvoiceRequest,
-) -> Result {
- let Some(mut hold_client) = plugin.state().hold_client.lock().clone() else {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::NotImplemented,
- message: "No hold plugin found".to_owned(),
- });
- };
-
- let preimage = match hex::decode(¶ms.preimage) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid preimage".to_owned(),
- });
- }
- };
-
- let hold_settle_request = SettleRequest {
- payment_preimage: preimage,
- };
-
- let hold_settle_response = hold_client.settle(hold_settle_request).await;
-
- match hold_settle_response {
- Ok(_o) => Ok(nip47::SettleHoldInvoiceResponse {}),
- Err(e) => Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- }),
- }
+ vec![(
+ nip47::Response {
+ result_type: nip47::Method::MakeHoldInvoice,
+ error: Some(nip47::NIP47Error {
+ code: nip47::ErrorCode::NotImplemented,
+ message: "Not implemented".to_owned(),
+ }),
+ result: None,
+ },
+ None,
+ )]
}
diff --git a/src/nwc_info.rs b/src/nwc_info.rs
index 27e196a..d3930e2 100644
--- a/src/nwc_info.rs
+++ b/src/nwc_info.rs
@@ -1,6 +1,6 @@
use cln_plugin::Plugin;
use cln_rpc::model::requests::GetinfoRequest;
-use nostr::nips::nip47;
+use nostr_sdk::nips::nip47;
use crate::{
structs::PluginState,
diff --git a/src/nwc_invoice.rs b/src/nwc_invoice.rs
index f521673..654a0b0 100644
--- a/src/nwc_invoice.rs
+++ b/src/nwc_invoice.rs
@@ -5,7 +5,7 @@ use cln_rpc::{
model::requests::InvoiceRequest,
primitives::{Amount, AmountOrAny, Sha256},
};
-use nostr::{nips::nip47, types::Timestamp};
+use nostr_sdk::nips::nip47;
use uuid::Uuid;
use crate::structs::PluginState;
@@ -94,8 +94,8 @@ async fn make_invoice(
description_hash: params.description_hash,
preimage: None,
amount: Some(params.amount),
- created_at: Some(Timestamp::now()),
- expires_at: Some(Timestamp::from_secs(o.expires_at)),
+ created_at: Some(nostr_sdk::nostr::Timestamp::now()),
+ expires_at: Some(nostr_sdk::nostr::Timestamp::from_secs(o.expires_at)),
}),
Err(e) => Err(nip47::NIP47Error {
code: nip47::ErrorCode::Internal,
diff --git a/src/nwc_keysend.rs b/src/nwc_keysend.rs
index aec724d..477db88 100644
--- a/src/nwc_keysend.rs
+++ b/src/nwc_keysend.rs
@@ -1,30 +1,18 @@
-use std::{collections::HashMap, str::FromStr};
+use std::{str::FromStr, time::Duration};
use cln_plugin::Plugin;
use cln_rpc::{
- ClnRpc,
- RpcError,
- model::requests::{KeysendRequest, XkeysendRequest},
- primitives::{Amount, PublicKey, Secret, TlvEntry, TlvStream},
+ model::requests::KeysendRequest,
+ primitives::{Amount, PublicKey, TlvEntry, TlvStream},
};
-use nostr::nips::nip47::{self};
+use nostr_sdk::nips::nip47;
+use tokio::time;
use crate::{
structs::PluginState,
- util::{
- budget_amount_check,
- get_budget_msat,
- load_nwc_store,
- payment_fee_reserve_msat,
- refund_budget,
- reserve_budget,
- rpc_socket_path,
- settle_budget,
- },
+ util::{budget_amount_check, load_nwc_store, update_nwc_store},
};
-pub const XKEYSEND_COMMAND: &str = "xkeysend";
-
pub async fn pay_keysend_response(
plugin: Plugin,
params: nip47::PayKeysendRequest,
@@ -61,6 +49,8 @@ async fn pay_keysend(
params: nip47::PayKeysendRequest,
label: &str,
) -> Result {
+ let mut rpc = plugin.state().rpc_lock.lock().await;
+
if params.preimage.is_some() {
return Err(nip47::NIP47Error {
code: nip47::ErrorCode::Other,
@@ -68,142 +58,32 @@ async fn pay_keysend(
});
}
+ let mut nwc_store = load_nwc_store(&mut rpc, label)
+ .await
+ .map_err(|e| nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ })?;
+
+ budget_amount_check(Some(params.amount), None, nwc_store.budget_msat).map_err(|e| {
+ nip47::NIP47Error {
+ code: nip47::ErrorCode::QuotaExceeded,
+ message: e.to_string(),
+ }
+ })?;
+
let pubkey = PublicKey::from_str(¶ms.pubkey).map_err(|e| nip47::NIP47Error {
code: nip47::ErrorCode::Other,
message: e.to_string(),
})?;
- let reservation = {
- let mut rpc = plugin.state().rpc_lock.lock().await;
-
- let nwc_store = load_nwc_store(&mut rpc, label)
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?;
-
- budget_amount_check(Some(params.amount), None, get_budget_msat(&nwc_store)).map_err(
- |e| nip47::NIP47Error {
- code: nip47::ErrorCode::QuotaExceeded,
- message: e.to_string(),
- },
- )?;
-
- // Reserve amount plus worst case fee so concurrent payments can never
- // exceed the budget.
- if get_budget_msat(&nwc_store).unwrap_or(u64::MAX)
- < params
- .amount
- .saturating_add(payment_fee_reserve_msat(params.amount))
- {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::QuotaExceeded,
- message: "Payment and estimated fees exceed the available budget".to_owned(),
- });
- }
-
- reserve_budget(&mut rpc, label, &nwc_store, params.amount)
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?
- };
-
- let has_xkeysend = plugin.state().config.lock().has_xkeysend;
- let mut pay_rpc =
- ClnRpc::new(rpc_socket_path(&plugin))
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: format!("Could not connect to lightningd: {e}"),
- })?;
-
- let pay_result = if has_xkeysend {
- xkeysend(&mut pay_rpc, ¶ms, pubkey).await
- } else {
- keysend(&mut pay_rpc, ¶ms, pubkey).await
- };
-
- match pay_result {
- Ok((amount_sent_msat, amount_msat, preimage)) => {
- let mut rpc = plugin.state().rpc_lock.lock().await;
- if let Err(e) = settle_budget(&mut rpc, label, reservation, amount_sent_msat).await {
- log::error!("Error updating budget after successful keysend: {e}");
- }
-
- let preimage = hex::encode(preimage.to_vec());
- let fees_paid = amount_sent_msat.saturating_sub(amount_msat);
-
- Ok(nip47::PayKeysendResponse {
- preimage,
- fees_paid: Some(fees_paid),
- })
- }
- Err(e) => {
- let mut rpc = plugin.state().rpc_lock.lock().await;
- if let Err(refund_err) = refund_budget(&mut rpc, label, reservation).await {
- log::error!(
- "Error refunding budget reservation after failed keysend: {refund_err}"
- );
- }
- Err(map_keysend_error(&e, has_xkeysend))
- }
- }
-}
-
-async fn xkeysend(
- pay_rpc: &mut ClnRpc,
- params: &nip47::PayKeysendRequest,
- pubkey: PublicKey,
-) -> Result<(u64, u64, Secret), RpcError> {
- let mut extratlvs = HashMap::with_capacity(params.tlv_records.len());
- for tlv in ¶ms.tlv_records {
- extratlvs.insert(tlv.tlv_type.to_string(), tlv.value.clone());
- }
- let extratlvs = if extratlvs.is_empty() {
- None
- } else {
- Some(extratlvs)
- };
-
- let o = pay_rpc
- .call_typed(&XkeysendRequest {
- extratlvs,
- label: None,
- maxdelay: None,
- maxfee: None,
- retry_for: None,
- layers: None,
- amount_msat: Amount::from_msat(params.amount),
- destination: pubkey,
- })
- .await?;
-
- Ok((
- o.amount_sent_msat.msat(),
- o.amount_msat.msat(),
- o.payment_preimage,
- ))
-}
-
-async fn keysend(
- pay_rpc: &mut ClnRpc,
- params: &nip47::PayKeysendRequest,
- pubkey: PublicKey,
-) -> Result<(u64, u64, Secret), RpcError> {
let mut extratlvs = TlvStream {
entries: Vec::new(),
};
- for tlv in ¶ms.tlv_records {
+ for tlv in params.tlv_records {
extratlvs.entries.push(TlvEntry {
typ: tlv.tlv_type,
- value: hex::decode(&tlv.value).map_err(|e| RpcError {
- code: Some(-32700),
- message: format!("Could not decode tlv bytes: {e}"),
- data: None,
- })?,
+ value: tlv.value.as_bytes().to_owned(),
});
}
let extratlvs = if extratlvs.entries.is_empty() {
@@ -212,7 +92,7 @@ async fn keysend(
Some(extratlvs)
};
- let o = pay_rpc
+ match rpc
.call_typed(&KeysendRequest {
exemptfee: None,
extratlvs,
@@ -225,48 +105,80 @@ async fn keysend(
amount_msat: Amount::from_msat(params.amount),
destination: pubkey,
})
- .await?;
+ .await
+ {
+ Ok(o) => {
+ if let Some(ref mut bdg) = nwc_store.budget_msat {
+ *bdg = bdg.saturating_sub(o.amount_sent_msat.msat());
+ update_nwc_store(&mut rpc, label, nwc_store)
+ .await
+ .map_err(|e| nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ })?;
+ }
- Ok((
- o.amount_sent_msat.msat(),
- o.amount_msat.msat(),
- o.payment_preimage,
- ))
-}
+ let preimage = hex::encode(o.payment_preimage.to_vec());
-fn map_keysend_error(e: &RpcError, is_xkeysend: bool) -> nip47::NIP47Error {
- let Some(c) = e.code else {
- return nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- };
- };
+ let fees_paid = o.amount_sent_msat.msat() - o.amount_msat.msat();
- let failed_codes = if is_xkeysend {
- vec![203, 205, 207, 219]
- } else {
- vec![203, 205, 210]
- };
-
- if failed_codes.contains(&c) {
- nip47::NIP47Error {
- code: nip47::ErrorCode::PaymentFailed,
- message: e.to_string(),
- }
- } else if is_xkeysend && c == 209 {
- nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: e.to_string(),
- }
- } else if !is_xkeysend && c == 206 {
- nip47::NIP47Error {
- code: nip47::ErrorCode::InsufficientBalance,
- message: e.to_string(),
- }
- } else {
- nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
+ Ok(nip47::PayKeysendResponse {
+ preimage,
+ fees_paid: Some(fees_paid),
+ })
}
+ Err(e) => match e.code {
+ Some(c) => match c {
+ 203 | 205 | 210 => Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::PaymentFailed,
+ message: e.to_string(),
+ }),
+ 206 => Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::InsufficientBalance,
+ message: e.to_string(),
+ }),
+ _ => Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ }),
+ },
+ None => Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ }),
+ },
}
}
+
+pub async fn multi_pay_keysend(
+ plugin: Plugin,
+ params: nip47::MultiPayKeysendRequest,
+ label: &str,
+) -> Vec<(nip47::Response, Option)> {
+ let mut responses = Vec::new();
+ for pay in params.keysends {
+ let result = pay_keysend(plugin.clone(), pay.clone(), label).await;
+ let id = if let Some(i) = pay.id { i } else { pay.pubkey };
+ let response_res = match result {
+ Ok(resp) => (
+ nip47::Response {
+ result_type: nip47::Method::MultiPayKeysend,
+ error: None,
+ result: Some(nip47::ResponseResult::MultiPayKeysend(resp)),
+ },
+ Some(id),
+ ),
+ Err(e) => (
+ nip47::Response {
+ result_type: nip47::Method::MultiPayKeysend,
+ error: Some(e),
+ result: None,
+ },
+ Some(id),
+ ),
+ };
+ responses.push(response_res);
+ time::sleep(Duration::from_millis(100)).await;
+ }
+ responses
+}
diff --git a/src/nwc_lookups.rs b/src/nwc_lookups.rs
index 42ce1f6..33bea1f 100644
--- a/src/nwc_lookups.rs
+++ b/src/nwc_lookups.rs
@@ -2,20 +2,9 @@ use std::{cmp::Reverse, str::FromStr};
use cln_plugin::Plugin;
use cln_rpc::{
- ClnRpc,
model::{
- requests::{
- DecodeRequest,
- ListinvoicesIndex,
- ListinvoicesRequest,
- ListpaysRequest,
- WaitIndexname,
- WaitRequest,
- WaitSubsystem,
- },
+ requests::{DecodeRequest, ListinvoicesRequest, ListpaysRequest},
responses::{
- DecodeResponse,
- DecodeType,
ListinvoicesInvoices,
ListinvoicesInvoicesStatus,
ListpaysPays,
@@ -23,22 +12,11 @@ use cln_rpc::{
},
},
primitives::Sha256,
+ ClnRpc,
};
-use nostr::{nips::nip47, types::Timestamp};
-use tonic::transport::Channel;
+use nostr_sdk::{nips::nip47, Timestamp};
-use crate::{
- hold::{self, ListRequest, hold_client::HoldClient, list_request::Constraint},
- structs::{NOT_INV_ERR, PluginState},
- util::rpc_socket_path,
-};
-
-#[allow(clippy::doc_markdown)]
-/// Hard bound on the number of transactions a single `list_transactions`
-/// request will fetch, decode and return (DoS protection).
-const MAX_TRANSACTIONS: usize = 500;
-/// Bound on the size of a `list_transactions` response in bytes.
-const RESPONSE_LIMIT_BYTES: usize = 127 * 1024;
+use crate::structs::{PluginState, NOT_INV_ERR};
pub async fn lookup_invoice_response(
plugin: Plugin,
@@ -80,7 +58,7 @@ async fn lookup_invoice(
let invoice = if params.payment_hash.is_some() && params.invoice.is_some() {
None
} else {
- params.invoice.clone()
+ params.invoice
};
let invoices = rpc
@@ -103,275 +81,46 @@ async fn lookup_invoice(
if invoices.len() == 1 {
let invoice_response = invoices.into_iter().next().unwrap();
- return make_lookup_response_from_listinvoices(&mut rpc, invoice_response).await;
- }
-
- let payment_hash_hash = if let Some(hash) = ¶ms.payment_hash {
- if let Ok(res) = Sha256::from_str(hash) {
- Some(res)
+ make_lookup_response_from_listinvoices(&mut rpc, invoice_response).await
+ } else {
+ let payment_hash_hash = if let Some(hash) = params.payment_hash {
+ if let Ok(res) = Sha256::from_str(&hash) {
+ Some(res)
+ } else {
+ return Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: "Could not convert payment hash".to_owned(),
+ });
+ }
} else {
- return Err(nip47::NIP47Error {
+ None
+ };
+
+ let pays = rpc
+ .call_typed(&ListpaysRequest {
+ bolt11: invoice,
+ index: None,
+ limit: None,
+ payment_hash: payment_hash_hash,
+ start: None,
+ status: None,
+ })
+ .await
+ .map_err(|e| nip47::NIP47Error {
code: nip47::ErrorCode::Internal,
- message: "Could not convert payment hash".to_owned(),
+ message: e.to_string(),
+ })?
+ .pays;
+
+ if pays.len() != 1 {
+ return Err(nip47::NIP47Error {
+ code: nip47::ErrorCode::NotFound,
+ message: "Transaction not found".to_owned(),
});
}
- } else {
- None
- };
-
- let pays = rpc
- .call_typed(&ListpaysRequest {
- bolt11: invoice,
- index: None,
- limit: None,
- payment_hash: payment_hash_hash,
- start: None,
- status: None,
- })
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?
- .pays;
-
- if pays.len() == 1 {
let list_pay = pays.into_iter().next().unwrap();
- return make_lookup_response_from_listpays(&mut rpc, list_pay).await;
- }
-
- let holdinvoice_support = plugin.state().hold_client.lock().is_some();
-
- if holdinvoice_support {
- let mut hold_client = plugin.state().hold_client.lock().clone().unwrap();
- return lookup_holdinvoice(&mut hold_client, &mut rpc, params).await;
- }
-
- Err(nip47::NIP47Error {
- code: nip47::ErrorCode::NotFound,
- message: "Transaction not found".to_owned(),
- })
-}
-
-async fn lookup_holdinvoice(
- hold_client: &mut HoldClient,
- rpc: &mut ClnRpc,
- params: nip47::LookupInvoiceRequest,
-) -> Result {
- log::debug!("Looking up hold invoice for params {params:#?}");
- let (hold_invoice, invoice_decoded) =
- get_and_decode_holdinvoice(rpc, hold_client, params).await?;
- let not_invoice_err = Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: NOT_INV_ERR.to_owned(),
- });
-
- let description = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => invoice_decoded.offer_description,
- DecodeType::BOLT11_INVOICE => invoice_decoded.description,
- _ => return not_invoice_err,
- };
- let description_hash = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => None,
- DecodeType::BOLT11_INVOICE => invoice_decoded.description_hash.map(|h| h.to_string()),
- _ => return not_invoice_err,
- };
-
- let created_at = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => {
- Timestamp::from_secs(invoice_decoded.invoice_created_at.unwrap())
- }
- DecodeType::BOLT11_INVOICE => Timestamp::from_secs(invoice_decoded.created_at.unwrap()),
- _ => return not_invoice_err,
- };
-
- let amount = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => invoice_decoded.invoice_amount_msat.unwrap().msat(),
- DecodeType::BOLT11_INVOICE => {
- if let Some(amt) = invoice_decoded.amount_msat {
- amt.msat()
- } else {
- // amount: `any` but have to put a value...
- 0
- }
- }
- _ => return not_invoice_err,
- };
-
- let expires_at = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => invoice_decoded
- .invoice_relative_expiry
- .map(|e_at| created_at + Timestamp::from_secs(u64::from(e_at))),
- DecodeType::BOLT11_INVOICE => invoice_decoded
- .expiry
- .map(|e_at| created_at + Timestamp::from_secs(e_at)),
- _ => return not_invoice_err,
- };
-
- let state = match hold_invoice.state() {
- hold::InvoiceState::Unpaid => nip47::TransactionState::Pending,
- hold::InvoiceState::Accepted => nip47::TransactionState::Accepted,
- hold::InvoiceState::Paid => nip47::TransactionState::Settled,
- hold::InvoiceState::Cancelled => nip47::TransactionState::Expired,
- };
-
- let settled_at = if hold_invoice.settled_at() != 0 {
- Some(Timestamp::from_secs(hold_invoice.settled_at()))
- } else {
- None
- };
-
- let preimage = if hold_invoice.state() == hold::InvoiceState::Paid {
- Some(hex::encode(hold_invoice.preimage()))
- } else {
- None
- };
-
- Ok(nip47::LookupInvoiceResponse {
- transaction_type: Some(nip47::TransactionType::Incoming),
- invoice: Some(hold_invoice.invoice.clone()),
- description,
- description_hash,
- preimage,
- payment_hash: hex::encode(hold_invoice.payment_hash),
- amount,
- fees_paid: 0,
- created_at,
- expires_at,
- settled_at,
- metadata: None,
- state: Some(state),
- })
-}
-
-#[allow(clippy::too_many_lines)]
-async fn get_and_decode_holdinvoice(
- rpc: &mut ClnRpc,
- hold_client: &mut HoldClient,
- params: nip47::LookupInvoiceRequest,
-) -> Result<(hold::Invoice, DecodeResponse), nip47::NIP47Error> {
- if let Some(ph) = ¶ms.payment_hash {
- let payment_hash_hash = match hex::decode(ph) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid payment hash".to_owned(),
- });
- }
- };
- let list_request = ListRequest {
- constraint: Some(Constraint::PaymentHash(payment_hash_hash)),
- };
- let hold_lookup = hold_client
- .list(list_request)
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: format!("Could not fetch hold invoice: {e}"),
- })?
- .into_inner();
-
- if hold_lookup.invoices.len() != 1 {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Transaction not found".to_owned(),
- });
- }
-
- let hold_invoice = hold_lookup.invoices.into_iter().next().unwrap();
- let invoice_decoded = rpc
- .call_typed(&DecodeRequest {
- string: hold_invoice.invoice.clone(),
- })
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?;
- if !invoice_decoded.valid {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid invoice decoded".to_owned(),
- });
- }
-
- Ok((hold_invoice, invoice_decoded))
- } else {
- let invoice_decoded = rpc
- .call_typed(&DecodeRequest {
- string: params.invoice.unwrap(),
- })
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?;
- if !invoice_decoded.valid {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid invoice decoded".to_owned(),
- });
- }
-
- let ph = match invoice_decoded.item_type {
- DecodeType::BOLT12_INVOICE => invoice_decoded.invoice_payment_hash.unwrap(),
- DecodeType::BOLT11_INVOICE => invoice_decoded.payment_hash.unwrap().to_string(),
- _ => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Not a supported invoice type".to_owned(),
- });
- }
- };
- let payment_hash_hash = match hex::decode(&ph) {
- Ok(p) => p,
- Err(_e) => {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid payment hash in invoice".to_owned(),
- });
- }
- };
-
- let list_request = ListRequest {
- constraint: Some(Constraint::PaymentHash(payment_hash_hash)),
- };
-
- let hold_lookup = hold_client
- .list(list_request)
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: format!("Could not fetch hold invoice: {e}"),
- })?
- .into_inner();
-
- if hold_lookup.invoices.len() != 1 {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Transaction not found".to_owned(),
- });
- }
-
- let hold_invoice = hold_lookup.invoices.into_iter().next().unwrap();
- let invoice_decoded = rpc
- .call_typed(&DecodeRequest {
- string: hold_invoice.invoice.clone(),
- })
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: e.to_string(),
- })?;
- if !invoice_decoded.valid {
- return Err(nip47::NIP47Error {
- code: nip47::ErrorCode::Other,
- message: "Invalid invoice decoded".to_owned(),
- });
- }
- Ok((hold_invoice, invoice_decoded))
+ make_lookup_response_from_listpays(&mut rpc, list_pay).await
}
}
@@ -403,37 +152,7 @@ async fn list_transactions(
plugin: Plugin,
params: nip47::ListTransactionsRequest,
) -> Result, nip47::NIP47Error> {
- if params.limit == Some(0) {
- return Ok(Vec::new());
- }
-
- let mut rpc = ClnRpc::new(rpc_socket_path(&plugin))
- .await
- .map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: format!("Could not connect to lightningd: {e}"),
- })?;
-
- let limit = usize::try_from(params.limit.unwrap_or(MAX_TRANSACTIONS as u64)).map_err(|e| {
- nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: format!("32-bit usize limit exceeded: {e}"),
- }
- })?;
- let offset = usize::try_from(params.offset.unwrap_or(0)).map_err(|e| nip47::NIP47Error {
- code: nip47::ErrorCode::Internal,
- message: format!("32-bit usize limit exceeded: {e}"),
- })?;
- let want = limit.saturating_add(offset);
- // Enough candidates from each source to satisfy the requested window even
- // if some get filtered out again by `from`/`until`/`unpaid`.
- let per_source = want
- .saturating_mul(2)
- .saturating_add(16)
- .min(MAX_TRANSACTIONS);
- let from = params.from.map(|t| t.as_secs());
- let until = params.until.map(|t| t.as_secs());
- let unpaid = params.unpaid.unwrap_or(false);
+ let mut rpc = plugin.state().rpc_lock.lock().await;
let (query_invoices, query_payments) = match params.transaction_type {
Some(t) => match t {
@@ -443,29 +162,62 @@ async fn list_transactions(
None => (true, true),
};
+ let unpaid = params.unpaid.unwrap_or(false);
+
let mut transactions: Vec = Vec::new();
-
if query_invoices {
- let invoices = collect_invoices(&mut rpc, per_source, from, until, unpaid).await?;
- transactions.extend(invoices);
+ let list_invoices = rpc
+ .call_typed(&ListinvoicesRequest {
+ index: None,
+ invstring: None,
+ label: None,
+ limit: None,
+ offer_id: None,
+ payment_hash: None,
+ start: None,
+ })
+ .await
+ .map_err(|e| nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ })?
+ .invoices;
- let hold_client = plugin.state().hold_client.lock().clone();
- if let Some(mut hold_client) = hold_client {
- list_holdinvoices_to_transactions(
- &mut hold_client,
- &mut rpc,
- per_source,
- from,
- until,
- &mut transactions,
- )
- .await?;
+ for list_invoice in list_invoices {
+ if !unpaid && list_invoice.status == ListinvoicesInvoicesStatus::UNPAID {
+ continue;
+ }
+
+ match make_lookup_response_from_listinvoices(&mut rpc, list_invoice).await {
+ Ok(t) => transactions.push(t),
+ Err(_e) => (),
+ }
}
}
if query_payments {
- let pays = collect_pays(&mut rpc, per_source, from, until).await?;
- transactions.extend(pays);
+ let list_pays = rpc
+ .call_typed(&ListpaysRequest {
+ bolt11: None,
+ index: None,
+ limit: None,
+ payment_hash: None,
+ start: None,
+ status: None,
+ })
+ .await
+ .map_err(|e| nip47::NIP47Error {
+ code: nip47::ErrorCode::Internal,
+ message: e.to_string(),
+ })?
+ .pays;
+
+ for list_pay in list_pays {
+ match make_lookup_response_from_listpays(&mut rpc, list_pay).await {
+ Ok(t) => transactions.push(t),
+ Err(_e) => (),
+ }
+ }
}
transactions.sort_by_key(|t| Reverse(t.created_at));
@@ -488,354 +240,11 @@ async fn list_transactions(
}
}
- transactions = trim_to_size(transactions, RESPONSE_LIMIT_BYTES);
+ transactions = trim_to_size(transactions, 127 * 1024);
Ok(transactions)
}
-async fn max_invoice_created_index(rpc: &mut ClnRpc) -> Result