cashubtc / cdk Goto Github PK
View Code? Open in Web Editor NEWCashu Development Kit
License: MIT License
Cashu Development Kit
License: MIT License
Mints with url path cannot be called because HttpClient removes the last part.
For mint url https://legend.lnbits.com/cashu/api/v1/4gr9Xcmz3XEkUNwiBiQGoC
HttpClient get keys from https://legend.lnbits.com/cashu/api/v1/keys
url
async fn main() {
let token = Token::from_str("cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6IjBOSTNUVUFzMVNmeSIsImFtb3VudCI6MSwic2VjcmV0IjoiVE92cGVmZGxSZ0EzdlhMN05pM2MvRE1oY29URXNQdnV4eFc0Rys2dXVycz0iLCJDIjoiMDNiZThmMzQwOTMxYTI4ZTlkMGRmNGFmMWQwMWY1ZTcxNTFkMmQ1M2RiN2Y0ZDAyMWQzZGUwZmRiMDNjZGY4ZTlkIn1dLCJtaW50IjoiaHR0cHM6Ly9sZWdlbmQubG5iaXRzLmNvbS9jYXNodS9hcGkvdjEvNGdyOVhjbXozWEVrVU53aUJpUUdvQyJ9XX0");
let mint_url = token.unwrap().token[0].mint.clone(); // https://legend.lnbits.com/cashu/api/v1/4gr9Xcmz3XEkUNwiBiQGoC
let client = HttpClient{};
let keys = client.get_mint_keys(&Url::from_str(mint_url.to_string().as_str()).unwrap()).await.unwrap(); // Request to https://legend.lnbits.com/cashu/api/v1/keys
}
The wallet-module in the cashu-sdk crate has several issues:
Solution:
#[async_trait(?Send)]
pub trait Client {
async fn get_keys(&self) -> Result<Keys, Error>
...
}
#[derive(Clone, Debug)]
pub struct Wallet<C: Client> {
pub client: C,
pub mint_keys: Keys,
pub balance: Amount,
}
This way we can have multiple implementations for clients (e.g. use reqwest for the regular desktop wallets and gloo-net for wasm clients) and get rid of the duplicated code for the logic in the wallet module
For unittests there can can also be an mock implementation using automock or a manual created one.
The refactoring would also fix this issue: #41
This is how I structured the wallet in my cashu-implementation https://github.com/ngutech21/moksha/blob/master/moksha-wallet/src/wallet.rs
Public key serialization/deserialization seems to be broken.
Running just final-check fails with a clippy error:
cargo clippy --locked --offline --workspace --all-targets -- --deny warnings --allow deprecated
warning: /Users/steffen/projects/cashu-crab/bindings/cashu-sdk-ffi/Cargo.toml: unused manifest key: dependencies.futures.feature
Checking cashu-sdk-ffi v0.1.0 (/Users/steffen/projects/cashu-crab/bindings/cashu-sdk-ffi)
error: variable `Invoice` should have a snake case name
--> /Users/steffen/projects/cashu-crab/target/debug/build/cashu-sdk-ffi-c6b10692a22ed522/out/cashu_sdk.uniffi.rs:2729:9
|
2729 | r#Invoice: ::uniffi::RustBuffer,
| ^^^^^^^^^ help: convert the identifier to snake case: `invoice`
|
= note: `-D non-snake-case` implied by `-D warnings`
error: variable `Invoice` should have a snake case name
--> /Users/steffen/projects/cashu-crab/target/debug/build/cashu-sdk-ffi-c6b10692a22ed522/out/cashu_sdk.uniffi.rs:3383:9
|
3383 | r#Invoice: ::uniffi::RustBuffer,
| ^^^^^^^^^ help: convert the identifier to snake case: `invoice`
error: could not compile `cashu-sdk-ffi` (lib) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
error: could not compile `cashu-sdk-ffi` (lib test) due to 2 previous errors
error: Recipe `clippy` failed on line 84 with exit code 101
There are multiple issues:
As a quick fix the --deny warnings can be omitted so the final-check action doesn't fails but just prints out a warning.
Think with this break only the first proof after amount available is > then send is added to change. This results in Proofs in != proofs out.
Check, add and document mint sanity checks.
In the SDK verify should probably be private and exposed only as part of the process function. Maybe a verification function should be added to the cashu crate.
git clone https://github.com/thesimplekid/cashu-crab.git
just build
-> compile error:
error[E0277]: `std::result::Result<Melted, cashu_sdk::wallet::Error>` is not a future
--> bindings/cashu-sdk-js/src/wallet.rs:154:14
|
154 | .await
| -^^^^^
| ||
| |`std::result::Result<Melted, cashu_sdk::wallet::Error>` is not a future
| help: remove the `.await`
|
= help: the trait `Future` is not implemented for `std::result::Result<Melted, cashu_sdk::wallet::Error>`
= note: std::result::Result<Melted, cashu_sdk::wallet::Error> must be a future or must implement `IntoFuture` to be awaited
= note: required for `std::result::Result<Melted, cashu_sdk::wallet::Error>` to implement `IntoFuture`
warning: call to `.deref()` on a reference in this situation does nothing
error[E0308]: mismatched types
--> bindings/cashu-sdk-js/src/wallet.rs:39:32
|
39 | inner: Wallet::new(client.deref().clone(), mint_keys.deref().clone()),
| ----------- ^^^^^^^^^^^^^^^^^^^^^^ expected `Client`, found a different `Client`
| |
| arguments to this function are incorrect
|
note: associated function defined here
cloning the repo and running just build without any feature flags compiles the workspace
JsClient.deref() returns a non-blocking client, which seems to be correct. But Wallet::new() expects a blocking client. I don't understand why this happens since blocking is an optional feature, that is not enabled by default.
Create a secret type instead of just a string
Hey, I was glancing over the code and saw that after the NUT-06 update here, you might have left some idiosyncrasies from earlier times in the code:
Since the mint does not know anything about "first" and "second" promises (blind signatures) anymore, you can treat these as one big slice and don't have to separate them anymore. Instead, the wallet now has to figure out which of the promises
it received it wants to keep and which to send on. I am guessing, this is what your code does here:
Keep up the insane work! Cheers!
Hi! I was having a look around the code and notice the library is using k256 instead of the rust-secp256k1 library. k256 is not cryptographic audited compared to rust-secp256k1 which is probably the most audited crypto library out there.
I was looking to work on a cashu library and found this package. do you think this would be a good change?
I would probably be interested in doing the change.
Decoding tokens where mint url have path cause error Base64Error(InvalidPadding)
Code to reproduce:
use cashu_sdk::nuts::nut00::wallet::Token;
fn main() {
let token = Token::from_str("cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6IjBOSTNUVUFzMVNmeSIsImFtb3VudCI6MSwic2VjcmV0IjoiVE92cGVmZGxSZ0EzdlhMN05pM2MvRE1oY29URXNQdnV4eFc0Rys2dXVycz0iLCJDIjoiMDNiZThmMzQwOTMxYTI4ZTlkMGRmNGFmMWQwMWY1ZTcxNTFkMmQ1M2RiN2Y0ZDAyMWQzZGUwZmRiMDNjZGY4ZTlkIn1dLCJtaW50IjoiaHR0cHM6Ly9sZWdlbmQubG5iaXRzLmNvbS9jYXNodS9hcGkvdjEvNGdyOVhjbXozWEVrVU53aUJpUUdvQyJ9XX0");
println!("Mint url: {}", token.unwrap().token[0].mint);
}
When I execute the code twice or more, it is possible to generate the same token, it should generate a completely different token.
Sometimes , even though the balance is sufficient, the call will return an error: Token already spent.
let r6 = api::send(1, "https://8333.space:3338/".to_string());
let r7 = api::send(1, "https://8333.space:3338/".to_string());
let r8 = api::send(1, "https://8333.space:3338/".to_string());
r6 :Ok(CashuTransaction(CashuTransaction { id: Some("991b5fcbe03fb8ddf50fcb94308e7579ecc82b589f2b6425cd0b0f510751ce98"), status: Pending(Send), time: 1692633929, amount: 1, mint: "https://8333.space:3338/", token: "cashuAeyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vODMzMy5zcGFjZTozMzM4IiwicHJvb2ZzIjpbXX1dLCJtZW1vIjpudWxsfQ==", from: None }))
r7 :Ok(CashuTransaction(CashuTransaction { id: Some("991b5fcbe03fb8ddf50fcb94308e7579ecc82b589f2b6425cd0b0f510751ce98"), status: Pending(Send), time: 1692633931, amount: 1, mint: "https://8333.space:3338/", token: "cashuAeyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vODMzMy5zcGFjZTozMzM4IiwicHJvb2ZzIjpbXX1dLCJtZW1vIjpudWxsfQ==", from: None }))
curl -X GET https://8333.space:3338/v1/keys
{"keysets":[{"id":"I2yN+iRYfkzT","unit":"sat","keys":{"1":"03ba786a2c0745f8c30e490288acd7a72dd53d65afd292ddefa326a4a3fa14c566","2":"03361cd8bd1329fea797a6add1cf1990ffcf2270ceb9fc81eeee0e8e9c1bd0cdf5","4":"036e37..
It's version is Nutshell/0.15.2
curl -X GET https://8333.space:3338/v1/info
{"name":"Cashu test mint","pubkey":"03e3d23e1b66eadaf15ce0d640a908e8ba1984baed34ab98c547aab4cf4249440d","version":"Nutshell/0.15.2","description":"This mint is for testing and development purposes only. Do not use this mint as a default mint in your application! Please use it with caution and only with very small amounts. Your Cashu client could have bugs. Accidents and bugs can lead to loss of funds for which we are not responsible for.","contact":[["",""]],"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","min_amount":0,"max_amount":500000}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat","min_amount":0,"max_amount":500000}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true}}}
Changes in cashubtc/nuts#82
The trailing slash should be handled better. It breaks round tripping token serializations
Likely need to create a crate url structs. Rust nostr does something similar
Trying to spend token and getting this error, it would be helpful to provide some Error message. Spending from nutstash works fine.
thread 'actix-rt|system:0|arbiter:1' panicked at cashu-crab/crates/cashu-sdk/src/mint.rs:309:42:
index out of bounds: the len is 1 but the index is 1
cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6InBvWFdrOG9OOU9MbCIsImFtb3VudCI6MSwic2VjcmV0IjoiVEtxcDVUdHdYTUtsb2I3MmxoRXI2Sjd6b2ZLWVhHakpDcHgzT0txbmJqUT0iLCJDIjoiMDJhYTViNjkwZTkzODY0ODE1ZGMwZDU2NzhiNWEzZDFjMDhhNTQ3MzczZDZiYmUyM2E4MzYyZjVhZGE5YTM1Yzg4In1dLCJtaW50IjoiaHR0cHM6Ly9jYXNodS50Y2hhaWNhcC5zcGFjZS9jYXNodSJ9XX0
Create an id type instead of just a string
Wallet should retry incrementing the counter until it finds one that isn't used
Double check all these test vectors are in tests
All combinations of features need to be tested.
Currently all optional nuts are as features in some cases it may make sense to remove the feature and include it as default. For example NUT08, its unlikely anyone disables this feature and having it behind a feature flag maybe more overhead then it is worth. NUT07 is also unlikely to go unused.
Only NUT13 adds extra external dependencies so that maybe the only one worth feature gating.
In some places they are called outputs. Should be consistent within the project
Instead of implementing the From-trait manually, I would recommend using thiserror crate https://docs.rs/thiserror/latest/thiserror/
This would get rid of most of the boilerplate code in the error types.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.