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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion payjoin-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@ url = { version = "2.5.4", features = ["serde"] }

[dev-dependencies]
nix = { version = "0.30.1", features = ["aio", "process", "signal"] }
payjoin-test-utils = { version = "0.0.1" }
payjoin-test-utils = { version = "0.0.1", features = ["bitcoind"] }
tempfile = "3.20.0"
1 change: 1 addition & 0 deletions payjoin-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ default = []
csharp = ["dep:uniffi-bindgen-cs"]
dart = ["dep:uniffi-dart"]
_test-utils = ["payjoin-test-utils", "tokio"]
_test-utils-bitcoind = ["_test-utils", "payjoin-test-utils/bitcoind"]
_manual-tls = ["payjoin/_manual-tls"]
wasm_js = ["getrandom/js"]

Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/contrib/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

# Individual features with no defaults.
features=("_manual-tls" "_test-utils")
features=("_manual-tls" "_test-utils" "_test-utils-bitcoind")

for feature in "${features[@]}"; do
# Don't duplicate --all-targets clippy. Clippy end-user code, not tests.
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/contrib/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e
RUST_VERSION=$(rustc --version | awk '{print $2}')

if [[ ! $RUST_VERSION =~ ^1\.85\. ]]; then
cargo test --package payjoin-ffi --verbose --features=_manual-tls,_test-utils
cargo test --package payjoin-ffi --verbose --features=_manual-tls,_test-utils-bitcoind
else
echo "Skipping payjoin-ffi tests for Rust version $RUST_VERSION (MSRV)"
fi
6 changes: 3 additions & 3 deletions payjoin-ffi/csharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ dotnet test

Generation uses the Cargo-managed C# generator from `payjoin-ffi/Cargo.toml`.

By default, generation builds `payjoin-ffi` with `_test-utils` enabled to keep parity with other language test scripts. Override via `PAYJOIN_FFI_FEATURES`.
By default, generation builds `payjoin-ffi` with `_test-utils-bitcoind` enabled to keep parity with other language test scripts. Override via `PAYJOIN_FFI_FEATURES`.

### Unix shells

```shell
export PAYJOIN_FFI_FEATURES=_test-utils # default behavior
export PAYJOIN_FFI_FEATURES=_test-utils-bitcoind # default behavior
# export PAYJOIN_FFI_FEATURES="" # build without extra features
bash ./scripts/generate_bindings.sh
```

### PowerShell

```powershell
$env:PAYJOIN_FFI_FEATURES = "_test-utils" # default behavior
$env:PAYJOIN_FFI_FEATURES = "_test-utils-bitcoind" # default behavior
# $env:PAYJOIN_FFI_FEATURES = "" # build without extra features
powershell -ExecutionPolicy Bypass -File .\scripts\generate_bindings.ps1
dotnet build
Expand Down
4 changes: 2 additions & 2 deletions payjoin-ffi/csharp/scripts/generate_bindings.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Write-Host "Generating payjoin C#..."
if ($null -ne $env:PAYJOIN_FFI_FEATURES) {
$payjoinFfiFeatures = $env:PAYJOIN_FFI_FEATURES
} else {
# Keep parity with other language test scripts: include _test-utils by default.
$payjoinFfiFeatures = "_test-utils"
# Keep parity with other language test scripts: include _test-utils-bitcoind by default.
$payjoinFfiFeatures = "_test-utils-bitcoind"
}

if ($payjoinFfiFeatures) {
Expand Down
4 changes: 2 additions & 2 deletions payjoin-ffi/csharp/scripts/generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/../.."

echo "Generating payjoin C#..."
# Keep parity with other language test scripts: include _test-utils by default.
PAYJOIN_FFI_FEATURES=${PAYJOIN_FFI_FEATURES:-_test-utils}
# Keep parity with other language test scripts: include _test-utils-bitcoind by default.
PAYJOIN_FFI_FEATURES=${PAYJOIN_FFI_FEATURES:-_test-utils-bitcoind}
GENERATOR_FEATURES="csharp"
if [[ -n $PAYJOIN_FFI_FEATURES ]]; then
GENERATOR_FEATURES="$GENERATOR_FEATURES,$PAYJOIN_FFI_FEATURES"
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/dart/hook/build.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ void main(List<String> args) async {
await build(args, (input, output) async {
await RustBuilder(
assetName: 'uniffi:payjoin_ffi',
features: ['_test-utils'],
features: ['_test-utils-bitcoind'],
).run(input: input, output: output);
});
}
1 change: 1 addition & 0 deletions payjoin-ffi/dart/native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ publish = false

[features]
_test-utils = ["payjoin-ffi/_test-utils"]
_test-utils-bitcoind = ["payjoin-ffi/_test-utils-bitcoind"]

[lib]
name = "payjoin_ffi_wrapper"
Expand Down
4 changes: 2 additions & 2 deletions payjoin-ffi/dart/scripts/generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fi

cd ../
echo "Generating payjoin dart..."
cargo build --features dart,_test-utils --profile dev
cargo run --features dart,_test-utils --profile dev --bin uniffi-bindgen -- --library ../target/debug/$LIBNAME --language dart --out-dir dart/lib/
cargo build --features dart,_test-utils-bitcoind --profile dev
cargo run --features dart,_test-utils-bitcoind --profile dev --bin uniffi-bindgen -- --library ../target/debug/$LIBNAME --language dart --out-dir dart/lib/

echo "All done!"
1 change: 1 addition & 0 deletions payjoin-ffi/javascript/test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "1.0.142"
tokio = { version = "1.47.1", features = ["full"] }

[dependencies.payjoin-test-utils]
features = ["bitcoind"]
path = "../../../payjoin-test-utils"

[build-dependencies]
Expand Down
10 changes: 5 additions & 5 deletions payjoin-ffi/python/scripts/generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ uv run python --version

cd ../
# This is a test script the actual release should not include the test utils feature
cargo build --features _test-utils --profile dev
cargo run --features _test-utils --profile dev --bin uniffi-bindgen generate --library ../target/debug/$LIBNAME --language python --out-dir python/src/payjoin/
cargo build --features _test-utils-bitcoind --profile dev
cargo run --features _test-utils-bitcoind --profile dev --bin uniffi-bindgen generate --library ../target/debug/$LIBNAME --language python --out-dir python/src/payjoin/

if [[ $OS == "Darwin" ]]; then
echo "Generating native binaries..."
rustup target add aarch64-apple-darwin x86_64-apple-darwin
# This is a test script the actual release should not include the test utils feature
cargo build --profile dev --target aarch64-apple-darwin --features _test-utils &
cargo build --profile dev --target x86_64-apple-darwin --features _test-utils &
cargo build --profile dev --target aarch64-apple-darwin --features _test-utils-bitcoind &
cargo build --profile dev --target x86_64-apple-darwin --features _test-utils-bitcoind &
wait

echo "Building macos fat library"
Expand All @@ -39,7 +39,7 @@ else
echo "Generating native binaries..."
rustup target add x86_64-unknown-linux-gnu
# This is a test script the actual release should not include the test utils feature
cargo build --profile dev --target x86_64-unknown-linux-gnu --features _test-utils
cargo build --profile dev --target x86_64-unknown-linux-gnu --features _test-utils-bitcoind

echo "Copying payjoin_ffi binary"
cp ../target/x86_64-unknown-linux-gnu/debug/$LIBNAME python/src/payjoin/$LIBNAME
Expand Down
80 changes: 80 additions & 0 deletions payjoin-ffi/src/test_utils/bitcoind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::sync::Arc;

use payjoin_test_utils::corepc_node::{self, AddressType};
use serde_json::Value;

#[derive(uniffi::Object)]
pub struct BitcoindEnv {
pub bitcoind: Arc<BitcoindInstance>,
pub receiver: Arc<RpcClient>,
pub sender: Arc<RpcClient>,
}

#[uniffi::export]
impl BitcoindEnv {
pub fn get_receiver(&self) -> Arc<RpcClient> { self.receiver.clone() }

pub fn get_sender(&self) -> Arc<RpcClient> { self.sender.clone() }

pub fn get_bitcoind(&self) -> Arc<BitcoindInstance> { self.bitcoind.clone() }
}

#[derive(uniffi::Object)]
pub struct BitcoindInstance {
_inner: corepc_node::Node,
}

#[derive(uniffi::Object)]
pub struct RpcClient {
inner: corepc_node::Client,
}

#[uniffi::export]
impl RpcClient {
pub fn call(&self, method: String, params: Vec<Option<String>>) -> Result<String, FfiError> {
let parsed_params: Vec<Value> = params
.into_iter()
.map(|param| match param {
Some(p) => serde_json::from_str(&p).unwrap_or(Value::String(p)),
None => Value::Null,
})
.collect();

let result = self
.inner
.call::<Value>(&method, &parsed_params)
.map_err(|e| FfiError::new(format!("RPC call failed: {e}")))?;

serde_json::to_string(&result)
.map_err(|e| FfiError::new(format!("Serialization error: {e}")))
}
}

#[derive(Debug, thiserror::Error, PartialEq, Eq, uniffi::Error)]
pub enum FfiError {
#[error("Init error: {0}")]
InitError(String),
#[error("Rpc error: {0}")]
RpcError(String),
#[error("{0}")]
Message(String),
}

impl FfiError {
pub fn new(msg: impl Into<String>) -> Self { FfiError::Message(msg.into()) }
}

#[uniffi::export]
pub fn init_bitcoind_sender_receiver() -> Result<Arc<BitcoindEnv>, FfiError> {
let (bitcoind, receiver, sender) = payjoin_test_utils::init_bitcoind_sender_receiver(
Some(AddressType::Bech32),
Some(AddressType::Bech32),
)
.map_err(|e| FfiError::InitError(e.to_string()))?;

Ok(Arc::new(BitcoindEnv {
bitcoind: Arc::new(BitcoindInstance { _inner: bitcoind }),
receiver: Arc::new(RpcClient { inner: receiver }),
sender: Arc::new(RpcClient { inner: sender }),
}))
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,23 @@ use std::io;
use std::sync::Arc;

use lazy_static::lazy_static;
use payjoin_test_utils::corepc_node::AddressType;
use payjoin_test_utils::{
corepc_node, EXAMPLE_URL, INVALID_PSBT, ORIGINAL_PSBT, PAYJOIN_PROPOSAL,
PAYJOIN_PROPOSAL_WITH_SENDER_INFO, QUERY_PARAMS, RECEIVER_INPUT_CONTRIBUTION,
EXAMPLE_URL, INVALID_PSBT, ORIGINAL_PSBT, PAYJOIN_PROPOSAL, PAYJOIN_PROPOSAL_WITH_SENDER_INFO,
QUERY_PARAMS, RECEIVER_INPUT_CONTRIBUTION,
};
use serde_json::Value;
use tokio::runtime::Runtime;
use tokio::sync::Mutex;

#[cfg(feature = "_test-utils-bitcoind")]
mod bitcoind;
#[cfg(feature = "_test-utils-bitcoind")]
pub use bitcoind::*;

lazy_static! {
static ref RUNTIME: Arc<std::sync::Mutex<Runtime>> =
Arc::new(std::sync::Mutex::new(Runtime::new().expect("Failed to create Tokio runtime")));
}

#[derive(uniffi::Object)]
pub struct BitcoindEnv {
pub bitcoind: Arc<BitcoindInstance>,
pub receiver: Arc<RpcClient>,
pub sender: Arc<RpcClient>,
}

#[uniffi::export]
impl BitcoindEnv {
pub fn get_receiver(&self) -> Arc<RpcClient> { self.receiver.clone() }

pub fn get_sender(&self) -> Arc<RpcClient> { self.sender.clone() }

pub fn get_bitcoind(&self) -> Arc<BitcoindInstance> { self.bitcoind.clone() }
}

#[derive(uniffi::Object)]
pub struct BitcoindInstance {
_inner: corepc_node::Node,
}

#[derive(uniffi::Object)]
pub struct RpcClient {
inner: corepc_node::Client,
}

#[uniffi::export]
impl RpcClient {
pub fn call(&self, method: String, params: Vec<Option<String>>) -> Result<String, FfiError> {
let parsed_params: Vec<Value> = params
.into_iter()
.map(|param| match param {
Some(p) => serde_json::from_str(&p).unwrap_or(Value::String(p)),
None => Value::Null,
})
.collect();

let result = self
.inner
.call::<Value>(&method, &parsed_params)
.map_err(|e| FfiError::new(format!("RPC call failed: {e}")))?;

serde_json::to_string(&result)
.map_err(|e| FfiError::new(format!("Serialization error: {e}")))
}
}

#[derive(Debug, thiserror::Error, PartialEq, Eq, uniffi::Error)]
pub enum FfiError {
#[error("Init error: {0}")]
InitError(String),
#[error("Rpc error: {0}")]
RpcError(String),
#[error("{0}")]
Message(String),
}

impl FfiError {
pub fn new(msg: impl Into<String>) -> Self { FfiError::Message(msg.into()) }
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error(transparent)]
pub struct BoxSendSyncError(#[from] payjoin_test_utils::BoxSendSyncError);
Expand Down Expand Up @@ -177,21 +119,6 @@ impl TestServices {
}
}

#[uniffi::export]
pub fn init_bitcoind_sender_receiver() -> Result<Arc<BitcoindEnv>, FfiError> {
let (bitcoind, receiver, sender) = payjoin_test_utils::init_bitcoind_sender_receiver(
Some(AddressType::Bech32),
Some(AddressType::Bech32),
)
.map_err(|e| FfiError::InitError(e.to_string()))?;

Ok(Arc::new(BitcoindEnv {
bitcoind: Arc::new(BitcoindInstance { _inner: bitcoind }),
receiver: Arc::new(RpcClient { inner: receiver }),
sender: Arc::new(RpcClient { inner: sender }),
}))
}

#[uniffi::export]
pub fn example_url() -> String { EXAMPLE_URL.to_string() }

Expand Down
9 changes: 8 additions & 1 deletion payjoin-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ repository = "https://github.com/payjoin/rust-payjoin"
rust-version = "1.85"
license = "MIT"

[features]
default = []
bitcoind = ["corepc-node"]

[dependencies]
axum-server = { version = "0.8", features = ["tls-rustls-no-provider"] }
bitcoin = { version = "0.32.7", features = ["base64"] }
corepc-node = { version = "0.10.0", features = ["download", "29_0"] }
corepc-node = { version = "0.10.0", features = [
"download",
"29_0",
], optional = true }
http = "1.3.1"
ohttp = { package = "bitcoin-ohttp", version = "0.6.0" }
once_cell = "1.21.3"
Expand Down
Loading
Loading