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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions payjoin-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ exclude = ["tests"]
[features]
_test-utils = ["payjoin-test-utils", "tokio", "bitcoind"]
_danger-local-https = ["payjoin/_danger-local-https"]
uniffi = ["uniffi/cli", "bitcoin-ffi/default", "uniffi-dart"]

[lib]
name = "payjoin_ffi"
Expand All @@ -19,7 +18,7 @@ name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"

[build-dependencies]
uniffi = { version = "0.29.1", features = ["build"] }
uniffi = { version = "0.29.1", features = ["build", "cli"] }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "b6186bc", features = ["build"] }

[dependencies]
Expand All @@ -35,8 +34,8 @@ serde = { version = "1.0.200", features = ["derive"] }
serde_json = "1.0.128"
thiserror = "1.0.58"
tokio = { version = "1.38.0", features = ["full"], optional = true }
uniffi = { version = "0.29.1", optional = true }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "b6186bc", optional = true}
uniffi = { version = "0.29.1" }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "b6186bc" }
url = "2.5.0"

[dev-dependencies]
Expand Down
10 changes: 0 additions & 10 deletions payjoin-ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,8 @@ This library should compile with any combination of features with Rust 1.78.0.
pip install payjoin

```
## Running the Integration Test


The integration tests illustrates and verify integration using bitcoin core and bdk.

```shell

# Run the integration test
cargo test --package payjoin_ffi --test bdk_integration_test v2_to_v2_full_cycle --features _danger-local-https


```
## References

[Payjoin Dev Kit](https://payjoindevkit.org/)
Expand Down
2 changes: 0 additions & 2 deletions payjoin-ffi/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
fn main() {
#[cfg(feature = "uniffi")]
uniffi::generate_scaffolding("src/payjoin_ffi.udl").unwrap();
#[cfg(feature = "uniffi")]
uniffi_dart::generate_scaffolding("src/payjoin_ffi.udl".into()).unwrap();
}
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=("uniffi" "_danger-local-https" "_test-utils")
features=("_danger-local-https" "_test-utils")

for feature in "${features[@]}"; do
# Don't duplicate --all-targets clippy. Clippy end-user code, not tests.
Expand Down
6 changes: 3 additions & 3 deletions payjoin-ffi/dart/scripts/generate_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ LINUX_TARGET=x86_64-unknown-linux-gnu
echo "Generating payjoin_ffi.dart..."
cd ../
# This is a test script the actual release should not include the test utils feature
cargo build --profile release --features uniffi,_test-utils
cargo run --profile release --features uniffi,_test-utils --bin uniffi-bindgen -- --library target/release/$LIBNAME --language dart --out-dir dart/lib/
cargo build --profile release --features _test-utils
cargo run --profile release --features _test-utils --bin uniffi-bindgen -- --library target/release/$LIBNAME --language dart --out-dir dart/lib/

echo "Generating native binaries..."
rustup target add $LINUX_TARGET
# This is a test script the actual release should not include the test utils feature
cargo build --profile release-smaller --target $LINUX_TARGET --features uniffi,_test-utils
cargo build --profile release-smaller --target $LINUX_TARGET --features _test-utils

echo "Copying linux payjoin_ffi.so"
cp target/$LINUX_TARGET/release-smaller/$LIBNAME dart/$LIBNAME
Expand Down
8 changes: 4 additions & 4 deletions payjoin-ffi/dart/scripts/generate_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ LIBNAME=libpayjoin_ffi.dylib
echo "Generating payjoin_ffi.dart..."
cd ../
# This is a test script the actual release should not include the test utils feature
cargo build --features uniffi,_test-utils --profile release
cargo run --features uniffi,_test-utils --profile release --bin uniffi-bindgen -- --library target/release/$LIBNAME --language dart --out-dir dart/lib/
cargo build --features _test-utils --profile release
cargo run --features _test-utils --profile release --bin uniffi-bindgen -- --library target/release/$LIBNAME --language dart --out-dir dart/lib/

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 release-smaller --target aarch64-apple-darwin --features uniffi,_test-utils
cargo build --profile release-smaller --target aarch64-apple-darwin --features _test-utils
echo "Done building aarch64-apple-darwin"

# This is a test script the actual release should not include the test utils feature
cargo build --profile release-smaller --target x86_64-apple-darwin --features uniffi,_test-utils
cargo build --profile release-smaller --target x86_64-apple-darwin --features _test-utils
echo "Done building x86_64-apple-darwin"

echo "Building macos fat library"
Expand Down
24 changes: 15 additions & 9 deletions payjoin-ffi/dart/test/test_payjoin_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,26 @@ Future<payjoin.PayjoinProposalReceiveSession> process_provisional_proposal(
payjoin.ProvisionalProposal proposal,
InMemoryReceiverPersister recv_persister) async {
final payjoin_proposal = proposal
.finalizeProposal(ProcessPsbtCallback(receiver), 1, 10)
.finalizeProposal(ProcessPsbtCallback(receiver))
.save(recv_persister);
return payjoin.PayjoinProposalReceiveSession(payjoin_proposal);
}

Future<payjoin.PayjoinProposalReceiveSession> process_wants_fee_range(
payjoin.WantsFeeRange proposal,
InMemoryReceiverPersister recv_persister) async {
final wants_fee_range = proposal.applyFeeRange(1, 10).save(recv_persister);
return await process_provisional_proposal(wants_fee_range, recv_persister);
}

Future<payjoin.PayjoinProposalReceiveSession> process_wants_inputs(
payjoin.WantsInputs proposal,
InMemoryReceiverPersister recv_persister) async {
final provisional_proposal = proposal
.contributeInputs(get_inputs(receiver))
.commitInputs()
.save(recv_persister);
return await process_provisional_proposal(
provisional_proposal, recv_persister);
return await process_wants_fee_range(provisional_proposal, recv_persister);
}

Future<payjoin.PayjoinProposalReceiveSession> process_wants_outputs(
Expand Down Expand Up @@ -240,12 +246,12 @@ Future<payjoin.ReceiveSession?> retrieve_receiver_proposal(
InMemoryReceiverPersister recv_persister,
payjoin.Url ohttp_relay) async {
var agent = http.Client();
var request = receiver.extractReq(ohttp_relay.asString());
var request = receiver.createPollRequest(ohttp_relay.asString());
var response = await agent.post(Uri.parse(request.request.url.asString()),
headers: {"Content-Type": request.request.contentType},
body: request.request.body);
var res = receiver
.processRes(response.bodyBytes, request.clientResponse)
.processResponse(response.bodyBytes, request.clientResponse)
.save(recv_persister);
if (res.isNone()) {
return null;
Expand Down Expand Up @@ -335,7 +341,7 @@ void main() {
.buildRecommended(1000)
.save(sender_persister);
payjoin.RequestV2PostContext request =
req_ctx.extractV2(ohttp_relay.asString());
req_ctx.createV2PostRequest(ohttp_relay.asString());
var response = await agent.post(Uri.parse(request.request.url.asString()),
headers: {"Content-Type": request.request.contentType},
body: request.request.body);
Expand All @@ -359,20 +365,20 @@ void main() {
payjoin.PayjoinProposal proposal =
(payjoin_proposal as payjoin.PayjoinProposalReceiveSession).inner;
payjoin.RequestResponse request_response =
proposal.extractReq(ohttp_relay.asString());
proposal.createPostRequest(ohttp_relay.asString());
var fallback_response = await agent.post(
Uri.parse(request_response.request.url.asString()),
headers: {"Content-Type": request_response.request.contentType},
body: request_response.request.body);
proposal.processRes(
proposal.processResponse(
fallback_response.bodyBytes, request_response.clientResponse);

// **********************
// Inside the Sender:
// Sender checks, isngs, finalizes, extracts, and broadcasts
// Replay post fallback to get the response
payjoin.RequestOhttpContext ohttp_context_request =
send_ctx.extractReq(ohttp_relay.asString());
send_ctx.createPollRequest(ohttp_relay.asString());
var final_response = await agent.post(
Uri.parse(ohttp_context_request.request.url.asString()),
headers: {"Content-Type": ohttp_context_request.request.contentType},
Expand Down
6 changes: 3 additions & 3 deletions payjoin-ffi/python/scripts/generate_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ LINUX_TARGET=x86_64-unknown-linux-gnu
echo "Generating payjoin_ffi.py..."
cd ../
# This is a test script the actual release should not include the test utils feature
cargo build --profile release --features uniffi,_test-utils
cargo run --profile release --features uniffi,_test-utils --bin uniffi-bindgen generate --library target/release/$LIBNAME --language python --out-dir python/src/payjoin/
cargo build --profile release --features _test-utils
cargo run --profile release --features _test-utils --bin uniffi-bindgen generate --library target/release/$LIBNAME --language python --out-dir python/src/payjoin/

echo "Generating native binaries..."
rustup target add $LINUX_TARGET
# This is a test script the actual release should not include the test utils feature
cargo build --profile release-smaller --target $LINUX_TARGET --features uniffi,_test-utils
cargo build --profile release-smaller --target $LINUX_TARGET --features _test-utils

echo "Copying linux payjoin_ffi.so"
cp target/$LINUX_TARGET/release-smaller/$LIBNAME python/src/payjoin/$LIBNAME
Expand Down
8 changes: 4 additions & 4 deletions payjoin-ffi/python/scripts/generate_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ LIBNAME=libpayjoin_ffi.dylib
echo "Generating payjoin_ffi.py..."
cd ../
# This is a test script the actual release should not include the test utils feature
cargo build --features uniffi,_test-utils --profile release
cargo run --features uniffi,_test-utils --profile release --bin uniffi-bindgen generate --library target/release/$LIBNAME --language python --out-dir python/src/payjoin/
cargo build --features _test-utils --profile release
cargo run --features _test-utils --profile release --bin uniffi-bindgen generate --library target/release/$LIBNAME --language python --out-dir python/src/payjoin/

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 release-smaller --target aarch64-apple-darwin --features uniffi,_test-utils
cargo build --profile release-smaller --target aarch64-apple-darwin --features _test-utils
echo "Done building aarch64-apple-darwin"

# This is a test script the actual release should not include the test utils feature
cargo build --profile release-smaller --target x86_64-apple-darwin --features uniffi,_test-utils
cargo build --profile release-smaller --target x86_64-apple-darwin --features _test-utils
echo "Done building x86_64-apple-darwin"

echo "Building macos fat library"
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/python/test/test_payjoin_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ async def test_integration_v2_to_v2(self):
headers={"Content-Type": request.request.content_type},
content=request.request.body
)
payjoin_proposal.process_res(response.content, request.client_response)
payjoin_proposal.process_response(response.content, request.client_response)

# **********************
# Inside the Sender:
Expand Down
14 changes: 2 additions & 12 deletions payjoin-ffi/src/bitcoin_ffi.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
use std::sync::Arc;

#[cfg(not(feature = "uniffi"))]
pub use bitcoin_ffi::*;
use payjoin::bitcoin;

#[cfg(feature = "uniffi")]
mod uni {
pub use bitcoin_ffi::*;
}

#[cfg(feature = "uniffi")]
pub use uni::*;

#[derive(Debug, Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[derive(Debug, Clone, uniffi::Record)]
pub struct PsbtInput {
pub witness_utxo: Option<TxOut>,
pub redeem_script: Option<Arc<Script>>,
Expand Down Expand Up @@ -55,7 +45,7 @@ impl From<PsbtInput> for bitcoin::psbt::Input {
}
}

#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[derive(uniffi::Record)]
pub struct Weight {
pub weight_units: u64,
}
Expand Down
10 changes: 3 additions & 7 deletions payjoin-ffi/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use std::error;
/// Error arising due to the specific receiver implementation
///
/// e.g. database errors, network failures, wallet errors
#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error(transparent)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
pub struct ImplementationError(#[from] payjoin::ImplementationError);

impl ImplementationError {
Expand All @@ -25,19 +24,16 @@ impl From<ImplementationError> for payjoin::ImplementationError {
fn from(value: ImplementationError) -> Self { value.0 }
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error("Error de/serializing JSON object: {0}")]
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
pub struct SerdeJsonError(#[from] serde_json::Error);

#[derive(Debug, thiserror::Error, PartialEq, Eq)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Error))]
#[derive(Debug, thiserror::Error, PartialEq, Eq, uniffi::Error)]
pub enum ForeignError {
#[error("Internal error: {0}")]
InternalError(String),
}

#[cfg(feature = "uniffi")]
impl From<uniffi::UnexpectedUniFFICallbackError> for ForeignError {
fn from(_: uniffi::UnexpectedUniFFICallbackError) -> Self {
Self::InternalError("Unexpected Uniffi callback error".to_string())
Expand Down
3 changes: 1 addition & 2 deletions payjoin-ffi/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ pub use error::IoError;
use crate::ohttp::OhttpKeys;

pub mod error {
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[derive(Debug, PartialEq, Eq, thiserror::Error, uniffi::Object)]
#[error("IO error: {message}")]
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
pub struct IoError {
message: String,
}
Expand Down
7 changes: 2 additions & 5 deletions payjoin-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ pub use payjoin::persist::NoopSessionPersister;
pub use crate::bitcoin_ffi::*;
pub use crate::ohttp::*;
pub use crate::output_substitution::*;
#[cfg(feature = "uniffi")]
pub use crate::receive::uni::*;
pub use crate::receive::*;
pub use crate::request::Request;
#[cfg(feature = "uniffi")]
pub use crate::send::uni::*;
pub use crate::send::*;
#[cfg(feature = "_test-utils")]
pub use crate::test_utils::*;
pub use crate::uri::{PjUri, Uri, Url};
#[cfg(feature = "uniffi")]
uniffi::setup_scaffolding!();
14 changes: 6 additions & 8 deletions payjoin-ffi/src/ohttp.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
pub use error::OhttpError;

pub mod error {
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
#[derive(Debug, PartialEq, Eq, thiserror::Error, uniffi::Object)]
#[error("OHTTP error: {message}")]
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
pub struct OhttpError {
message: String,
}
Expand All @@ -21,20 +20,19 @@ impl From<payjoin::OhttpKeys> for OhttpKeys {
impl From<OhttpKeys> for payjoin::OhttpKeys {
fn from(value: OhttpKeys) -> Self { value.0 }
}
#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
#[derive(Debug, Clone)]
#[derive(Debug, Clone, uniffi::Object)]
pub struct OhttpKeys(payjoin::OhttpKeys);

#[cfg_attr(feature = "uniffi", uniffi::export)]
#[uniffi::export]
impl OhttpKeys {
/// Decode an OHTTP KeyConfig
#[cfg_attr(feature = "uniffi", uniffi::constructor)]
#[uniffi::constructor]
pub fn decode(bytes: Vec<u8>) -> Result<Self, OhttpError> {
payjoin::OhttpKeys::decode(bytes.as_slice()).map(Into::into).map_err(Into::into)
}

/// Create an OHTTP KeyConfig from a string
#[cfg_attr(feature = "uniffi", uniffi::constructor)]
#[uniffi::constructor]
pub fn from_string(s: String) -> Result<Self, OhttpError> {
let res = payjoin::OhttpKeys::from_str(s.as_str())
.map_err(|e| OhttpError::from(e.to_string()))?;
Expand All @@ -45,7 +43,7 @@ impl OhttpKeys {
use std::str::FromStr;
use std::sync::Mutex;

#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
#[derive(uniffi::Object)]
pub struct ClientResponse(Mutex<Option<ohttp::ClientResponse>>);

impl From<&ClientResponse> for ohttp::ClientResponse {
Expand Down
3 changes: 1 addition & 2 deletions payjoin-ffi/src/output_substitution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub type OutputSubstitution = payjoin::OutputSubstitution;

#[cfg(feature = "uniffi")]
#[cfg_attr(feature = "uniffi", uniffi::remote(Enum))]
#[uniffi::remote(Enum)]
enum OutputSubstitution {
Enabled,
Disabled,
Expand Down
Loading
Loading