diff --git a/Cargo.toml b/Cargo.toml index 342a37dc..dd836ea1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "crates/cashu-sdk", "bindings/uniffi-bindgen", "bindings/cashu-ffi", + "bindings/cashu-sdk-ffi" ] [workspace.package] diff --git a/bindings/cashu-sdk-ffi/Cargo.toml b/bindings/cashu-sdk-ffi/Cargo.toml new file mode 100644 index 00000000..55520276 --- /dev/null +++ b/bindings/cashu-sdk-ffi/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "cashu-sdk-ffi" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "cashu_sdk_ffi" +crate-type = ["cdylib", "staticlib"] + + +[dependencies] +cashu-ffi = { path = "../cashu-ffi" } +cashu-sdk = { path = "../../crates/cashu-sdk", default-features = false, features = ["wallet", "mint", "blocking"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +uniffi = { workspace = true } + +[build-dependencies] +uniffi = { workspace = true, features = ["build"] } + diff --git a/bindings/cashu-sdk-ffi/LICENSE b/bindings/cashu-sdk-ffi/LICENSE new file mode 100644 index 00000000..083823dd --- /dev/null +++ b/bindings/cashu-sdk-ffi/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023, thesimplekid +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bindings/cashu-sdk-ffi/LICENSES/NOSTR_SDK_LICENSE_MIT b/bindings/cashu-sdk-ffi/LICENSES/NOSTR_SDK_LICENSE_MIT new file mode 100644 index 00000000..2ff56442 --- /dev/null +++ b/bindings/cashu-sdk-ffi/LICENSES/NOSTR_SDK_LICENSE_MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023 Yuki Kishimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bindings/cashu-sdk-ffi/README.md b/bindings/cashu-sdk-ffi/README.md new file mode 100644 index 00000000..e69de29b diff --git a/bindings/cashu-sdk-ffi/bindings-python/.gitignore b/bindings/cashu-sdk-ffi/bindings-python/.gitignore new file mode 100644 index 00000000..f186bda5 --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/.gitignore @@ -0,0 +1,17 @@ +.tox/ +dist/ +cashu_sdk.egg-info/ +__pycache__/ +libnostr_sdk_ffi.dylib +.idea/ +.DS_Store + +*.swp + +src/cashu-sdk/cashu_sdk.py +src/cashu-sdk/*.so +*.whl +build/ + +testing-setup-py-simple-example.py + diff --git a/bindings/cashu-sdk-ffi/bindings-python/LICENSE b/bindings/cashu-sdk-ffi/bindings-python/LICENSE new file mode 100644 index 00000000..083823dd --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023, thesimplekid +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bindings/cashu-sdk-ffi/bindings-python/LICENSES/NOSTR_SDK_MIT b/bindings/cashu-sdk-ffi/bindings-python/LICENSES/NOSTR_SDK_MIT new file mode 100644 index 00000000..2ff56442 --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/LICENSES/NOSTR_SDK_MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023 Yuki Kishimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bindings/cashu-sdk-ffi/bindings-python/MANIFEST.in b/bindings/cashu-sdk-ffi/bindings-python/MANIFEST.in new file mode 100644 index 00000000..ebf6ce8c --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/MANIFEST.in @@ -0,0 +1,3 @@ +include ./src/cashu-sdk/libcashu_sdk_ffi.dylib +include ./src/cashu-sdk/libcashu_sdk_ffi.so + diff --git a/bindings/cashu-sdk-ffi/bindings-python/README.md b/bindings/cashu-sdk-ffi/bindings-python/README.md new file mode 100644 index 00000000..e69de29b diff --git a/bindings/cashu-sdk-ffi/bindings-python/pyproject.toml b/bindings/cashu-sdk-ffi/bindings-python/pyproject.toml new file mode 100644 index 00000000..0e557d58 --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/pyproject.toml @@ -0,0 +1,7 @@ +[build-system] +requires = ["setuptools", "wheel"] + +[tool.pytest.ini_options] +pythonpath = [ + "." +] diff --git a/bindings/cashu-sdk-ffi/bindings-python/requirements.txt b/bindings/cashu-sdk-ffi/bindings-python/requirements.txt new file mode 100644 index 00000000..099ef548 --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/requirements.txt @@ -0,0 +1,5 @@ +semantic-version==2.9.0 +typing_extensions==4.0.1 +setuptools==67.4.0 +wheel==0.38.4 + diff --git a/bindings/cashu-sdk-ffi/bindings-python/setup.py b/bindings/cashu-sdk-ffi/bindings-python/setup.py new file mode 100644 index 00000000..720de203 --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/setup.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +from setuptools import setup + +from pathlib import Path +this_directory = Path(__file__).parent +long_description = (this_directory / "README.md").read_text() + +setup( + name='cashu-sdk', + version='0.0.1', + description="High level client library.", + long_description=long_description, + long_description_content_type='text/markdown', + include_package_data=True, + zip_safe=False, + packages=['cashu_sdk'], + package_dir={'cashu_sdk': './src/cashu-sdk'}, + url="https://github.com/thesimplekid/cashu-crab", + author="thesimplekid ", + license="BSD-3-Clause", + # This is required to ensure the library name includes the python version, abi, and platform tags + # See issue #350 for more information + has_ext_modules=lambda: True, +) + diff --git a/bindings/cashu-sdk-ffi/bindings-python/src/cashu-sdk/__init__.py b/bindings/cashu-sdk-ffi/bindings-python/src/cashu-sdk/__init__.py new file mode 100644 index 00000000..506a65dd --- /dev/null +++ b/bindings/cashu-sdk-ffi/bindings-python/src/cashu-sdk/__init__.py @@ -0,0 +1,2 @@ +from cashu_sdk.cashu_sdk import * + diff --git a/bindings/cashu-sdk-ffi/build.rs b/bindings/cashu-sdk-ffi/build.rs new file mode 100644 index 00000000..0db24ea7 --- /dev/null +++ b/bindings/cashu-sdk-ffi/build.rs @@ -0,0 +1,3 @@ +fn main() { + uniffi::generate_scaffolding("./src/cashu_sdk.udl").expect("Building the UDL file failed"); +} diff --git a/bindings/cashu-sdk-ffi/justfile b/bindings/cashu-sdk-ffi/justfile new file mode 100644 index 00000000..3c360bfc --- /dev/null +++ b/bindings/cashu-sdk-ffi/justfile @@ -0,0 +1,16 @@ +init: + rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim + rustup target add aarch64-apple-darwin x86_64-apple-darwin + rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android + cargo install cbindgen + cargo install cargo-ndk + +python: + rm -rf dist + pip install -r bindings-python/requirements.txt + cargo build --release + cargo run -p uniffi-bindgen generate src/cashu_sdk.udl --language python --no-format -o bindings-python/src/cashu-sdk/ + cp ../../target/release/libcashu_sdk_ffi.so bindings-python/src/cashu-sdk/ + cp ../../target/release/libcashu_sdk_ffi.dylib bindings-python/src/cashu-sdk/ | true + cd bindings-python && pip wheel --no-deps -w dist . + pip install ./bindings-python/dist/cashu_sdk*.whl --force-reinstall diff --git a/bindings/cashu-sdk-ffi/src/cashu_sdk.udl b/bindings/cashu-sdk-ffi/src/cashu_sdk.udl new file mode 100644 index 00000000..8a429b0f --- /dev/null +++ b/bindings/cashu-sdk-ffi/src/cashu_sdk.udl @@ -0,0 +1,219 @@ +namespace cashu_sdk {}; + +// Cashu + +[Error] +interface CashuError { + Generic(string err); +}; + +interface Amount { + u64 to_sat(); + u64 to_msat(); + [Name = from_sat] + constructor(u64 sat); + [Name = from_msat] + constructor(u64 msat); + sequence split(); +}; + + +interface PublicKey { + [Throws=CashuError, Name=from_hex] + constructor(string hex); + [Throws=CashuError] + string to_hex(); +}; + + +interface SecretKey { + [Throws=CashuError, Name=from_hex] + constructor(string hex); + [Throws=CashuError] + string to_hex(); +}; + +interface BlindedMessage { + constructor(Amount amount, PublicKey b); + Amount amount(); + PublicKey b(); +}; + +interface Proof { + constructor(Amount amount, string secret, PublicKey c, string? id); + Amount amount(); + string secret(); + PublicKey c(); + string? id(); +}; + +interface BlindedSignature { + constructor(string id, Amount amount, PublicKey c); + string id(); + Amount amount(); + PublicKey c(); +}; + +interface MintProof { + constructor(Amount? amount, string secret, PublicKey? c, string? id); + Amount? amount(); + string secret(); + PublicKey? c(); + string? id(); + +}; + +interface MintProofs { + [Throws=CashuError] + constructor(string mint, sequence proofs); + string url(); + sequence proofs(); +}; + +interface Token { + [Throws=CashuError] + constructor(string mint, sequence token, string? memo); + sequence token(); + string? memo(); + [Throws=CashuError] + string as_string(); + [Throws=CashuError, Name=from_string] + constructor(string token); + +}; + +interface BlindedMessages { + [Throws=CashuError, Name=random] + constructor(Amount amount); + [Throws=CashuError, Name=blank] + constructor(Amount fee_reserve); + sequence blinded_messages(); + sequence secrets(); + sequence rs(); + sequence amounts(); +}; + +interface KeyPair { + [Name=from_secret_key] + constructor(SecretKey secret_key); + SecretKey secret_key(); + PublicKey public_key(); +}; + +interface Keys { + constructor(record keys); + record keys(); + record as_hashmap(); + PublicKey? amount_key(Amount amount); +}; + +interface KeySet { + constructor(string id, Keys keys); + string id(); + Keys keys(); +}; + +interface KeySetResponse { + constructor(sequence keyset_ids); + sequence keyset_ids(); +}; + +interface RequestMintResponse { + [Throws=CashuError] + constructor(string invoice, string hash); + string invoice(); + string hash(); +}; + +interface MintRequest { + constructor(sequence outputs); + sequence outputs(); + Amount total_amount(); +}; + +interface PostMintResponse { + constructor(sequence promises); + sequence promises(); +}; + +interface CheckFeesRequest { + [Throws=CashuError] + constructor(string invoice); + string invoice(); +}; + +interface CheckFeesResponse { + constructor(Amount amount); + Amount amount(); +}; + +interface Nut05MeltRequest { + [Throws=CashuError] + constructor(sequence proofs, string Invoice); + sequence proofs(); + string invoice(); +}; + +interface Nut05MeltResponse { + constructor(boolean paid, string? preimage); + boolean paid(); + string? preimage(); +}; + +interface SplitRequest { + constructor(sequence proofs, sequence outputs); + sequence proofs(); + sequence outputs(); + Amount proofs_amount(); + Amount output_amount(); +}; + +interface SplitResponse { + constructor(sequence promises); + sequence promises(); + Amount? promises_amount(); + +}; + +interface CheckSpendableRequest { + constructor(sequence proofs); + sequence proofs(); +}; + +interface CheckSpendableResponse { + constructor(sequence spendable, sequence pending); + sequence spendable(); + sequence pending(); +}; + +interface MeltRequest { + [Throws=CashuError] + constructor(sequence proofs, string Invoice, sequence? outputs); + sequence proofs(); + string invoice(); + sequence? outputs(); +}; + +interface MeltResponse { + constructor(boolean paid, string? preimage, sequence? change); + boolean paid(); + string? preimage(); + sequence? change(); +}; + +interface MintVersion { + constructor(string name, string version); + string name(); + string version(); +}; + +interface MintInfo { + constructor(string? name, PublicKey? pubkey, MintVersion? version, string? description, string? description_long, sequence> contact, sequence nuts, string? motd); +}; + +enum InvoiceStatus { + "Unpaid", + "Paid", + "Expired", + "InFlight" +}; \ No newline at end of file diff --git a/bindings/cashu-sdk-ffi/src/lib.rs b/bindings/cashu-sdk-ffi/src/lib.rs new file mode 100644 index 00000000..745e9fe5 --- /dev/null +++ b/bindings/cashu-sdk-ffi/src/lib.rs @@ -0,0 +1,14 @@ +mod ffi { + pub use cashu_ffi::{ + Amount, BlindedMessage, BlindedMessages, BlindedSignature, CashuError, CheckFeesRequest, + CheckFeesResponse, CheckSpendableRequest, CheckSpendableResponse, InvoiceStatus, KeyPair, + KeySet, KeySetResponse, Keys, MeltRequest, MeltResponse, MintInfo, MintProof, MintProofs, + MintRequest, MintVersion, Nut05MeltRequest, Nut05MeltResponse, PostMintResponse, Proof, + PublicKey, RequestMintResponse, SecretKey, SplitRequest, SplitResponse, Token, + }; + + // UDL + uniffi::include_scaffolding!("cashu_sdk"); +} + +pub use ffi::*; diff --git a/bindings/cashu-sdk-ffi/uniffi.toml b/bindings/cashu-sdk-ffi/uniffi.toml new file mode 100644 index 00000000..26944880 --- /dev/null +++ b/bindings/cashu-sdk-ffi/uniffi.toml @@ -0,0 +1,11 @@ +[bindings.kotlin] +package_name = "cashu_sdk" +cdylib_name = "cashu_sdk_ffi" + +[bindings.swift] +ffi_module_filename = "cashu_sdkFFI" +cdylib_name = "cashu_sdk_ffi" + +[bindings.python] +cdylib_name = "cashu_sdk_ffi" +