mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-09 07:06:12 +01:00
bindings/cashu-sdk: add ffi bindings for mint and wallet
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
[[language]]
|
||||
name = "rust"
|
||||
config = { cargo = { features = [ "blocking", "wallet" ] } }
|
||||
config = { cargo = { features = [ "blocking", "wallet", "mint" ] } }
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cashu = { path = "../../crates/cashu", featues = ["wallet", "mint"] }
|
||||
cashu = { path = "../../crates/cashu", features = ["wallet", "mint"] }
|
||||
url = { workspace = true }
|
||||
uniffi = { workspace = true }
|
||||
|
||||
|
||||
@@ -6,56 +6,6 @@ init:
|
||||
cargo install cbindgen
|
||||
cargo install cargo-ndk
|
||||
|
||||
|
||||
kotlin:
|
||||
$(JUST) ffi-kotlin-clean
|
||||
$(JUST) ffi-kotlin-generate
|
||||
|
||||
ffi-kotlin-clean:
|
||||
find ./ffi/kotlin/jniLibs -name libcashu_sdk_ffi.so -type f -delete
|
||||
|
||||
ffi-kotlin-generate:
|
||||
cargo run -p uniffi-bindgen generate src/cashu.udl --language kotlin --no-format -o ffi/kotlin
|
||||
|
||||
android: aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
|
||||
|
||||
aarch64-linux-android:
|
||||
cargo ndk -t aarch64-linux-android -o ffi/kotlin/jniLibs build --release
|
||||
|
||||
armv7-linux-androideabi:
|
||||
$(JUST) ffi-ndk-build TARGET=armv7-linux-androideabi
|
||||
|
||||
i686-linux-android:
|
||||
$(JUST) ffi-ndk-build TARGET=i686-linux-android
|
||||
|
||||
x86_64-linux-android:
|
||||
$(JUST) ffi-ndk-build TARGET=x86_64-linux-android
|
||||
|
||||
ffi-ndk-build:
|
||||
cargo ndk -t $(TARGET) -o ffi/kotlin/jniLibs build --release
|
||||
|
||||
bindings-android:
|
||||
$(JUST) bindings-android-clean
|
||||
$(JUST) bindings-android-copy
|
||||
cd bindings-android && ./gradlew assemble
|
||||
$(JUST) bindings-android-package
|
||||
|
||||
bindings-android-clean:
|
||||
rm -rf bindings-android/lib/src/main/jniLibs
|
||||
rm -rf bindings-android/lib/src/main/kotlin
|
||||
|
||||
bindings-android-copy:
|
||||
cp -r ffi/kotlin/jniLibs bindings-android/lib/src/main
|
||||
cp -r ffi/kotlin/cashu bindings-android/lib/src/main/kotlin/
|
||||
|
||||
bindings-android-package:
|
||||
mkdir -p ffi/android
|
||||
cp bindings-android/lib/build/outputs/aar/lib-release.aar ffi/android
|
||||
|
||||
publish-android:
|
||||
cd bindings-android && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
|
||||
|
||||
|
||||
python:
|
||||
rm -rf dist
|
||||
pip install -r bindings-python/requirements.txt
|
||||
|
||||
@@ -59,3 +59,15 @@ impl BlindedMessages {
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut00::wallet::BlindedMessages> for BlindedMessages {
|
||||
fn from(inner: cashu::nuts::nut00::wallet::BlindedMessages) -> BlindedMessages {
|
||||
BlindedMessages { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlindedMessages> for cashu::nuts::nut00::wallet::BlindedMessages {
|
||||
fn from(blinded_messages: BlindedMessages) -> cashu::nuts::nut00::wallet::BlindedMessages {
|
||||
blinded_messages.inner
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,14 +32,12 @@ impl MintProofs {
|
||||
}
|
||||
|
||||
pub fn proofs(&self) -> Vec<Arc<Proof>> {
|
||||
let proofs = self
|
||||
.inner
|
||||
self.inner
|
||||
.proofs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect();
|
||||
proofs
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::MintProofs;
|
||||
use crate::Proof;
|
||||
|
||||
pub struct Token {
|
||||
token: TokenSdk,
|
||||
inner: TokenSdk,
|
||||
}
|
||||
|
||||
impl Token {
|
||||
@@ -16,12 +16,12 @@ impl Token {
|
||||
let mint = url::Url::from_str(&mint)?;
|
||||
let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
|
||||
Ok(Self {
|
||||
token: TokenSdk::new(mint, proofs, memo)?,
|
||||
inner: TokenSdk::new(mint, proofs, memo)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Vec<Arc<MintProofs>> {
|
||||
self.token
|
||||
self.inner
|
||||
.token
|
||||
.clone()
|
||||
.into_iter()
|
||||
@@ -30,16 +30,22 @@ impl Token {
|
||||
}
|
||||
|
||||
pub fn memo(&self) -> Option<String> {
|
||||
self.token.memo.clone()
|
||||
self.inner.memo.clone()
|
||||
}
|
||||
|
||||
pub fn from_string(token: String) -> Result<Self> {
|
||||
Ok(Self {
|
||||
token: TokenSdk::from_str(&token)?,
|
||||
inner: TokenSdk::from_str(&token)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Result<String> {
|
||||
Ok(self.token.convert_to_string()?)
|
||||
Ok(self.inner.convert_to_string()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut00::wallet::Token> for Token {
|
||||
fn from(inner: cashu::nuts::nut00::wallet::Token) -> Token {
|
||||
Token { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,3 +53,9 @@ impl KeySetResponse {
|
||||
self.inner.clone().keysets.into_iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut02::Response> for KeySetResponse {
|
||||
fn from(inner: Response) -> KeySetResponse {
|
||||
KeySetResponse { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,3 +25,11 @@ impl RequestMintResponse {
|
||||
self.inner.hash.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut03::RequestMintResponse> for RequestMintResponse {
|
||||
fn from(mint_response: cashu::nuts::nut03::RequestMintResponse) -> RequestMintResponse {
|
||||
RequestMintResponse {
|
||||
inner: mint_response,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,3 +56,9 @@ impl PostMintResponse {
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut04::PostMintResponse> for PostMintResponse {
|
||||
fn from(inner: cashu::nuts::nut04::PostMintResponse) -> PostMintResponse {
|
||||
PostMintResponse { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,18 @@ impl CheckFeesResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut05::CheckFeesResponse> for CheckFeesResponse {
|
||||
fn from(inner: cashu::nuts::nut05::CheckFeesResponse) -> CheckFeesResponse {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CheckFeesResponse> for cashu::nuts::nut05::CheckFeesResponse {
|
||||
fn from(res: CheckFeesResponse) -> cashu::nuts::nut05::CheckFeesResponse {
|
||||
res.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MeltRequest {
|
||||
inner: MeltRequestSdk,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use cashu::nuts::nut06::{SplitRequest as SplitRequestSdk, SplitResponse as SplitResponseSdk};
|
||||
|
||||
@@ -8,6 +8,13 @@ pub struct SplitRequest {
|
||||
inner: SplitRequestSdk,
|
||||
}
|
||||
|
||||
impl Deref for SplitRequest {
|
||||
type Target = SplitRequestSdk;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl SplitRequest {
|
||||
pub fn new(proofs: Vec<Arc<Proof>>, outputs: Vec<Arc<BlindedMessage>>) -> Self {
|
||||
let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
|
||||
@@ -79,3 +86,9 @@ impl SplitResponse {
|
||||
self.inner.promises_amount().map(|a| Arc::new(a.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut06::SplitResponse> for SplitResponse {
|
||||
fn from(inner: cashu::nuts::nut06::SplitResponse) -> SplitResponse {
|
||||
SplitResponse { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,3 +49,9 @@ impl CheckSpendableResponse {
|
||||
self.inner.pending.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut07::CheckSpendableResponse> for CheckSpendableResponse {
|
||||
fn from(inner: cashu::nuts::nut07::CheckSpendableResponse) -> CheckSpendableResponse {
|
||||
CheckSpendableResponse { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,3 +85,15 @@ impl MeltResponse {
|
||||
.map(|change| change.into_iter().map(|bs| Arc::new(bs.into())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut08::MeltResponse> for MeltResponse {
|
||||
fn from(inner: cashu::nuts::nut08::MeltResponse) -> MeltResponse {
|
||||
MeltResponse { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MeltResponse> for cashu::nuts::nut08::MeltResponse {
|
||||
fn from(res: MeltResponse) -> cashu::nuts::nut08::MeltResponse {
|
||||
res.inner
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,3 +74,9 @@ impl MintInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu::nuts::nut09::MintInfo> for MintInfo {
|
||||
fn from(inner: cashu::nuts::nut09::MintInfo) -> MintInfo {
|
||||
MintInfo { inner }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,4 @@ src/cashu-sdk/*.so
|
||||
*.whl
|
||||
build/
|
||||
|
||||
testing-setup-py-simple-example.py
|
||||
|
||||
|
||||
3
bindings/cashu-sdk-ffi/bindings-python/examples/test.py
Normal file
3
bindings/cashu-sdk-ffi/bindings-python/examples/test.py
Normal file
@@ -0,0 +1,3 @@
|
||||
import cashu_sdk;
|
||||
|
||||
help(cashu_sdk)
|
||||
@@ -7,6 +7,14 @@ interface CashuError {
|
||||
Generic(string err);
|
||||
};
|
||||
|
||||
|
||||
interface Bolt11Invoice {
|
||||
[Throws=CashuError]
|
||||
constructor(string bolt11);
|
||||
string as_string();
|
||||
Amount? amount();
|
||||
};
|
||||
|
||||
interface Amount {
|
||||
u64 to_sat();
|
||||
u64 to_msat();
|
||||
@@ -216,4 +224,73 @@ enum InvoiceStatus {
|
||||
"Paid",
|
||||
"Expired",
|
||||
"InFlight"
|
||||
};
|
||||
|
||||
// Cashu Sdk
|
||||
|
||||
|
||||
[Error]
|
||||
interface CashuSdkError {
|
||||
Generic(string err);
|
||||
};
|
||||
|
||||
interface SendProofs {
|
||||
constructor(sequence<Proof> change_proofs, sequence<Proof> send_proofs);
|
||||
sequence<Proof> send_proofs();
|
||||
sequence<Proof> change_proofs();
|
||||
};
|
||||
|
||||
interface Melted {
|
||||
constructor(boolean paid, string? preimage, sequence<Proof>? change);
|
||||
string? preimage();
|
||||
boolean paid();
|
||||
sequence<Proof>? change();
|
||||
};
|
||||
|
||||
interface Client {
|
||||
[Throws=CashuSdkError]
|
||||
constructor(string mint_url);
|
||||
[Throws=CashuSdkError]
|
||||
Keys get_keys();
|
||||
[Throws=CashuSdkError]
|
||||
KeySetResponse get_keysets();
|
||||
[Throws=CashuSdkError]
|
||||
RequestMintResponse request_mint(Amount amount);
|
||||
[Throws=CashuSdkError]
|
||||
PostMintResponse mint(BlindedMessages blinded_messages, string hash);
|
||||
[Throws=CashuSdkError]
|
||||
CheckFeesResponse check_fees(Bolt11Invoice invoice);
|
||||
[Throws=CashuSdkError]
|
||||
MeltResponse melt(sequence<Proof> proofs, Bolt11Invoice invoice, sequence<BlindedMessage>? outputs);
|
||||
[Throws=CashuSdkError]
|
||||
SplitResponse split(SplitRequest split_request);
|
||||
[Throws=CashuSdkError]
|
||||
CheckSpendableResponse check_spendable(sequence<MintProof> proofs);
|
||||
[Throws=CashuSdkError]
|
||||
MintInfo get_info();
|
||||
};
|
||||
|
||||
interface Wallet {
|
||||
constructor(Client client, Keys mint_keys);
|
||||
// TODO: ProofStatus type
|
||||
// [Throws=CashuSdkError]
|
||||
// ProofsStatus check_proofs_spent(sequence<MintProof> proofs);
|
||||
[Throws=CashuSdkError]
|
||||
RequestMintResponse request_mint(Amount amount);
|
||||
[Throws=CashuSdkError]
|
||||
Token mint_token(Amount amount, string hash);
|
||||
[Throws=CashuSdkError]
|
||||
sequence<Proof> mint(Amount amount, string hash);
|
||||
[Throws=CashuSdkError]
|
||||
Amount check_fee(Bolt11Invoice invoice);
|
||||
[Throws=CashuSdkError]
|
||||
sequence<Proof> receive(string encoded_token);
|
||||
[Throws=CashuSdkError]
|
||||
sequence<Proof> process_split_response(BlindedMessages blinded_messages, sequence<BlindedSignature> promises);
|
||||
[Throws=CashuSdkError]
|
||||
SendProofs send(Amount amount, sequence<Proof> proofs);
|
||||
[Throws=CashuSdkError]
|
||||
Melted melt(Bolt11Invoice invoice, sequence<Proof> proofs, Amount fee_reserve);
|
||||
[Throws=CashuSdkError]
|
||||
string proof_to_token(sequence<Proof> proof, string? memo);
|
||||
};
|
||||
105
bindings/cashu-sdk-ffi/src/client.rs
Normal file
105
bindings/cashu-sdk-ffi/src/client.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cashu_ffi::{
|
||||
BlindedMessage, BlindedMessages, Bolt11Invoice, CheckFeesResponse, CheckSpendableResponse,
|
||||
KeySetResponse, MeltResponse, MintInfo, MintProof, PostMintResponse, Proof,
|
||||
RequestMintResponse, SplitRequest, SplitResponse,
|
||||
};
|
||||
use cashu_sdk::client::blocking::Client as ClientSdk;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::{Amount, Keys};
|
||||
|
||||
pub struct Client {
|
||||
inner: ClientSdk,
|
||||
}
|
||||
|
||||
impl Deref for Client {
|
||||
type Target = ClientSdk;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(mint_url: String) -> Result<Self> {
|
||||
Ok(Self {
|
||||
inner: ClientSdk::new(&mint_url)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_keys(&self) -> Result<Arc<Keys>> {
|
||||
Ok(Arc::new(self.inner.get_keys()?.into()))
|
||||
}
|
||||
|
||||
pub fn get_keysets(&self) -> Result<Arc<KeySetResponse>> {
|
||||
Ok(Arc::new(self.inner.get_keysets()?.into()))
|
||||
}
|
||||
|
||||
pub fn request_mint(&self, amount: Arc<Amount>) -> Result<Arc<RequestMintResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner.request_mint(*amount.as_ref().deref())?.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn mint(
|
||||
&self,
|
||||
blinded_messages: Arc<BlindedMessages>,
|
||||
hash: String,
|
||||
) -> Result<Arc<PostMintResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.mint(blinded_messages.as_ref().deref().clone(), &hash)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn check_fees(&self, invoice: Arc<Bolt11Invoice>) -> Result<Arc<CheckFeesResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.check_fees(invoice.as_ref().deref().clone())?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn melt(
|
||||
&self,
|
||||
proofs: Vec<Arc<Proof>>,
|
||||
invoice: Arc<Bolt11Invoice>,
|
||||
outputs: Option<Vec<Arc<BlindedMessage>>>,
|
||||
) -> Result<Arc<MeltResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.melt(
|
||||
proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
|
||||
invoice.as_ref().deref().clone(),
|
||||
outputs.map(|bs| bs.iter().map(|b| b.as_ref().deref().clone()).collect()),
|
||||
)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn split(&self, split_request: Arc<SplitRequest>) -> Result<Arc<SplitResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.split(split_request.as_ref().deref().clone())?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn check_spendable(
|
||||
&self,
|
||||
proofs: Vec<Arc<MintProof>>,
|
||||
) -> Result<Arc<CheckSpendableResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.check_spendable(&proofs.iter().map(|p| p.as_ref().deref().clone()).collect())?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_info(&self) -> Result<Arc<MintInfo>> {
|
||||
Ok(Arc::new(self.inner.get_info()?.into()))
|
||||
}
|
||||
}
|
||||
32
bindings/cashu-sdk-ffi/src/error.rs
Normal file
32
bindings/cashu-sdk-ffi/src/error.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use std::fmt;
|
||||
|
||||
pub type Result<T, E = CashuSdkError> = std::result::Result<T, E>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CashuSdkError {
|
||||
Generic { err: String },
|
||||
}
|
||||
|
||||
impl fmt::Display for CashuSdkError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Generic { err } => write!(f, "{err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu_sdk::client::Error> for CashuSdkError {
|
||||
fn from(err: cashu_sdk::client::Error) -> CashuSdkError {
|
||||
Self::Generic {
|
||||
err: err.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu_sdk::wallet::Error> for CashuSdkError {
|
||||
fn from(err: cashu_sdk::wallet::Error) -> CashuSdkError {
|
||||
Self::Generic {
|
||||
err: err.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,23 @@
|
||||
mod client;
|
||||
mod error;
|
||||
mod types;
|
||||
mod wallet;
|
||||
|
||||
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,
|
||||
Amount, BlindedMessage, BlindedMessages, BlindedSignature, Bolt11Invoice, 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,
|
||||
};
|
||||
|
||||
pub use crate::client::Client;
|
||||
pub use crate::error::CashuSdkError;
|
||||
pub use crate::types::{Melted, SendProofs};
|
||||
pub use crate::wallet::Wallet;
|
||||
|
||||
// UDL
|
||||
uniffi::include_scaffolding!("cashu_sdk");
|
||||
}
|
||||
|
||||
42
bindings/cashu-sdk-ffi/src/types/melted.rs
Normal file
42
bindings/cashu-sdk-ffi/src/types/melted.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use cashu_sdk::types::Melted as MeltedSdk;
|
||||
|
||||
use cashu_ffi::Proof;
|
||||
|
||||
pub struct Melted {
|
||||
inner: MeltedSdk,
|
||||
}
|
||||
|
||||
impl Melted {
|
||||
pub fn new(paid: bool, preimage: Option<String>, change: Option<Vec<Arc<Proof>>>) -> Self {
|
||||
Self {
|
||||
inner: MeltedSdk {
|
||||
paid,
|
||||
preimage,
|
||||
change: change.map(|c| c.iter().map(|p| p.as_ref().deref().clone()).collect()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preimage(&self) -> Option<String> {
|
||||
self.inner.preimage.clone()
|
||||
}
|
||||
|
||||
pub fn paid(&self) -> bool {
|
||||
self.inner.paid
|
||||
}
|
||||
|
||||
pub fn change(&self) -> Option<Vec<Arc<Proof>>> {
|
||||
self.inner
|
||||
.change
|
||||
.clone()
|
||||
.map(|c| c.into_iter().map(|p| Arc::new(p.into())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu_sdk::types::Melted> for Melted {
|
||||
fn from(inner: cashu_sdk::types::Melted) -> Melted {
|
||||
Melted { inner }
|
||||
}
|
||||
}
|
||||
5
bindings/cashu-sdk-ffi/src/types/mod.rs
Normal file
5
bindings/cashu-sdk-ffi/src/types/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod melted;
|
||||
pub mod send_proofs;
|
||||
|
||||
pub use melted::Melted;
|
||||
pub use send_proofs::SendProofs;
|
||||
50
bindings/cashu-sdk-ffi/src/types/send_proofs.rs
Normal file
50
bindings/cashu-sdk-ffi/src/types/send_proofs.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use cashu_sdk::types::SendProofs as SendProofSdk;
|
||||
|
||||
use cashu_ffi::Proof;
|
||||
|
||||
pub struct SendProofs {
|
||||
inner: SendProofSdk,
|
||||
}
|
||||
|
||||
impl SendProofs {
|
||||
pub fn new(change_proofs: Vec<Arc<Proof>>, send_proofs: Vec<Arc<Proof>>) -> Self {
|
||||
Self {
|
||||
inner: SendProofSdk {
|
||||
change_proofs: change_proofs
|
||||
.iter()
|
||||
.map(|p| p.as_ref().deref().clone())
|
||||
.collect(),
|
||||
send_proofs: send_proofs
|
||||
.iter()
|
||||
.map(|p| p.as_ref().deref().clone())
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_proofs(&self) -> Vec<Arc<Proof>> {
|
||||
self.inner
|
||||
.send_proofs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn change_proofs(&self) -> Vec<Arc<Proof>> {
|
||||
self.inner
|
||||
.change_proofs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cashu_sdk::types::SendProofs> for SendProofs {
|
||||
fn from(inner: cashu_sdk::types::SendProofs) -> SendProofs {
|
||||
SendProofs { inner }
|
||||
}
|
||||
}
|
||||
127
bindings/cashu-sdk-ffi/src/wallet.rs
Normal file
127
bindings/cashu-sdk-ffi/src/wallet.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cashu_ffi::{
|
||||
BlindedMessages, BlindedSignature, Bolt11Invoice, Proof, RequestMintResponse, Token,
|
||||
};
|
||||
use cashu_sdk::types::ProofsStatus;
|
||||
use cashu_sdk::wallet::Wallet as WalletSdk;
|
||||
|
||||
use crate::{
|
||||
client::Client,
|
||||
error::Result,
|
||||
types::{Melted, SendProofs},
|
||||
Amount, Keys, MintProof,
|
||||
};
|
||||
|
||||
pub struct Wallet {
|
||||
inner: WalletSdk,
|
||||
}
|
||||
|
||||
impl Wallet {
|
||||
pub fn new(client: Arc<Client>, mint_keys: Arc<Keys>) -> Self {
|
||||
Self {
|
||||
inner: WalletSdk::new(
|
||||
client.as_ref().deref().clone(),
|
||||
mint_keys.as_ref().deref().clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_proofs_spent(&self, proofs: Vec<Arc<MintProof>>) -> Result<Arc<ProofsStatus>> {
|
||||
Ok(Arc::new(self.inner.check_proofs_spent(
|
||||
&proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
|
||||
)?))
|
||||
}
|
||||
|
||||
pub fn request_mint(&self, amount: Arc<Amount>) -> Result<Arc<RequestMintResponse>> {
|
||||
Ok(Arc::new(
|
||||
self.inner.request_mint(*amount.as_ref().deref())?.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn mint_token(&self, amount: Arc<Amount>, hash: String) -> Result<Arc<Token>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.mint_token(*amount.as_ref().deref(), &hash)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn mint(&self, amount: Arc<Amount>, hash: String) -> Result<Vec<Arc<Proof>>> {
|
||||
Ok(self
|
||||
.inner
|
||||
.mint(*amount.as_ref().deref(), &hash)?
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn check_fee(&self, invoice: Arc<Bolt11Invoice>) -> Result<Arc<Amount>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.check_fee(invoice.as_ref().deref().clone())?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn receive(&self, encoded_token: String) -> Result<Vec<Arc<Proof>>> {
|
||||
Ok(self
|
||||
.inner
|
||||
.receive(&encoded_token)?
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn process_split_response(
|
||||
&self,
|
||||
blinded_messages: Arc<BlindedMessages>,
|
||||
promises: Vec<Arc<BlindedSignature>>,
|
||||
) -> Result<Vec<Arc<Proof>>> {
|
||||
Ok(self
|
||||
.inner
|
||||
.process_split_response(
|
||||
blinded_messages.as_ref().deref().clone(),
|
||||
promises.iter().map(|p| p.as_ref().deref().into()).collect(),
|
||||
)?
|
||||
.into_iter()
|
||||
.map(|p| Arc::new(p.into()))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn send(&self, amount: Arc<Amount>, proofs: Vec<Arc<Proof>>) -> Result<Arc<SendProofs>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.send(
|
||||
*amount.as_ref().deref(),
|
||||
proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
|
||||
)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn melt(
|
||||
&self,
|
||||
invoice: Arc<Bolt11Invoice>,
|
||||
proofs: Vec<Arc<Proof>>,
|
||||
fee_reserve: Arc<Amount>,
|
||||
) -> Result<Arc<Melted>> {
|
||||
Ok(Arc::new(
|
||||
self.inner
|
||||
.melt(
|
||||
invoice.as_ref().deref().clone(),
|
||||
proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
|
||||
*fee_reserve.as_ref().deref(),
|
||||
)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn proof_to_token(&self, proofs: Vec<Arc<Proof>>, memo: Option<String>) -> Result<String> {
|
||||
Ok(self.inner.proofs_to_token(
|
||||
proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
|
||||
memo,
|
||||
)?)
|
||||
}
|
||||
}
|
||||
@@ -44,10 +44,10 @@ impl Client {
|
||||
|
||||
pub fn mint(
|
||||
&self,
|
||||
blinded_mssages: BlindedMessages,
|
||||
blinded_messages: BlindedMessages,
|
||||
hash: &str,
|
||||
) -> Result<PostMintResponse, Error> {
|
||||
RUNTIME.block_on(async { self.client.mint(blinded_mssages, hash).await })
|
||||
RUNTIME.block_on(async { self.client.mint(blinded_messages, hash).await })
|
||||
}
|
||||
|
||||
pub fn check_fees(&self, invoice: Bolt11Invoice) -> Result<CheckFeesResponse, Error> {
|
||||
|
||||
@@ -88,7 +88,7 @@ impl Keys {
|
||||
self.0.get(&amount.to_sat()).cloned()
|
||||
}
|
||||
|
||||
/// As seralized hashmap
|
||||
/// As serialized hashmap
|
||||
pub fn as_hashmap(&self) -> HashMap<u64, String> {
|
||||
self.0
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user