diff --git a/Cargo.lock b/Cargo.lock index b06e7bf..20947fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,6 +56,18 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -65,6 +77,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "anyhow" version = "1.0.86" @@ -426,6 +444,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "daggy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a9304e55e9d601a39ae4deaba85406d5c0980e106f65afcf0460e9af1e7602" +dependencies = [ + "petgraph", +] + [[package]] name = "delegate-display" version = "2.1.1" @@ -506,6 +533,18 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fancy_constructor" version = "1.2.2" @@ -749,6 +788,19 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] [[package]] name = "heck" @@ -993,6 +1045,17 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1355,6 +1418,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "poly1305" version = "0.8.0" @@ -1626,6 +1695,21 @@ dependencies = [ "digest", ] +[[package]] +name = "rusqlite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", + "time", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1719,6 +1803,29 @@ dependencies = [ "zip32", ] +[[package]] +name = "schemer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835d8f9478fd2936195fc941a8666b0d0894d5bf3631cbb884a8ce8ba631f339" +dependencies = [ + "daggy", + "log", + "thiserror", + "uuid", +] + +[[package]] +name = "schemer-rusqlite" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fb5ac1fa52c58e2c6a618e3149d464e7ad8d0effca74990ea29c1fe2338b3b1" +dependencies = [ + "rusqlite", + "schemer", + "uuid", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -1914,11 +2021,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "js-sys", "num-conv", "powerfmt", "serde", "time-core", + "time-macros", ] [[package]] @@ -1927,6 +2036,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -2249,6 +2368,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" @@ -2471,6 +2596,7 @@ dependencies = [ "secrecy", "sha2", "subtle", + "tempfile", "thiserror", "tokio", "tonic", @@ -2485,6 +2611,7 @@ dependencies = [ "zcash_address", "zcash_client_backend", "zcash_client_memory", + "zcash_client_sqlite", "zcash_keys", "zcash_primitives", "zcash_proofs", @@ -2701,6 +2828,42 @@ dependencies = [ "zip32", ] +[[package]] +name = "zcash_client_sqlite" +version = "0.11.2" +source = "git+https://github.com/ChainSafe/librustzcash?rev=a77e8a0204dab421fdbf5822e585716339567b96#a77e8a0204dab421fdbf5822e585716339567b96" +dependencies = [ + "bs58", + "byteorder", + "document-features", + "group", + "incrementalmerkletree", + "jubjub", + "maybe-rayon", + "nonempty", + "orchard", + "prost 0.13.2", + "regex", + "rusqlite", + "sapling-crypto", + "schemer", + "schemer-rusqlite", + "secrecy", + "shardtree", + "static_assertions", + "subtle", + "time", + "tracing", + "uuid", + "zcash_address", + "zcash_client_backend", + "zcash_encoding", + "zcash_keys", + "zcash_primitives", + "zcash_protocol", + "zip32", +] + [[package]] name = "zcash_encoding" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index da49fb8..7bdd97c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ default = ["native"] wasm = ["console_error_panic_hook", "dep:tracing-web"] native = ["dep:tokio", "tonic/channel", "tonic/gzip", "tonic/tls-webpki-roots"] - +sqlite-db = ["dep:zcash_client_sqlite"] console_error_panic_hook = ["dep:console_error_panic_hook"] [dependencies] @@ -55,6 +55,7 @@ tonic = { version = "0.12", default-features = false, features = [ # Used in Native tests tokio = { version = "1.0", features = ["rt", "macros"], optional = true } +zcash_client_sqlite = { git = "https://github.com/ChainSafe/librustzcash", rev = "a77e8a0204dab421fdbf5822e585716339567b96", default-features = false, features = ["unstable", "orchard"], optional = true } getrandom = { version = "0.2", features = ["js"] } thiserror = "1.0.63" @@ -72,6 +73,7 @@ subtle = "2.6.1" [dev-dependencies] wasm-bindgen-test = "0.3.42" +tempfile = "3.12" [patch.crates-io] zip32 = { git = "https://github.com/zcash/zip32.git", branch = "diversifier_index_ord"} diff --git a/justfile b/justfile index 7b4d8bc..e1e007a 100644 --- a/justfile +++ b/justfile @@ -10,5 +10,8 @@ test-web: test-native: cargo test -r -- --nocapture +test-sqlite: + cargo test -r --features="sqlite-db" test_get_and_scan_range_native_sqlite -- --nocapture + check: cargo check diff --git a/src/error.rs b/src/error.rs index 283a6ef..fb12f12 100644 --- a/src/error.rs +++ b/src/error.rs @@ -44,6 +44,10 @@ pub enum Error { InvalidAmount(#[from] zcash_primitives::transaction::components::amount::BalanceError), #[error("Failed to send transaction")] SendFailed { code: i32, reason: String }, + + #[cfg(feature = "sqlite-db")] + #[error("Sqlite error: {0}")] + SqliteError(#[from] zcash_client_sqlite::error::SqliteClientError), } impl From for JsValue { diff --git a/tests/tests.rs b/tests/tests.rs index 9e41d76..5cee2e5 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -95,3 +95,62 @@ async fn test_get_and_scan_range_native() { let summary = w.get_wallet_summary().unwrap(); tracing::info!("Wallet summary: {:?}", summary); } + +#[cfg(all(feature = "native", feature = "sqlite-db"))] +#[tokio::test] +async fn test_get_and_scan_range_native_sqlite() { + use tempfile::{tempdir, NamedTempFile}; + use zcash_client_sqlite::{ + chain::init::init_blockmeta_db, wallet::init::init_wallet_db, FsBlockDb, WalletDb, + }; + use zcash_primitives::consensus; + + initialize(); + let url = "https://testnet.zec.rocks:443"; + let c = tonic::transport::Channel::from_shared(url).unwrap(); + + let tls = tonic::transport::ClientTlsConfig::new() + .domain_name("testnet.zec.rocks") + .with_webpki_roots(); + let channel = c.tls_config(tls).unwrap(); + + let db_cache = tempdir().unwrap(); + let db_data = NamedTempFile::new_in(db_cache.path()).unwrap(); + + let mut db_cache = FsBlockDb::for_path(&db_cache).unwrap(); + let mut wallet_db = WalletDb::for_path(&db_data, consensus::Network::TestNetwork).unwrap(); + init_blockmeta_db(&mut db_cache).unwrap(); + init_wallet_db(&mut wallet_db, None).unwrap(); + + let mut w = Wallet::new( + wallet_db, + channel.connect().await.unwrap(), + Network::TestNetwork, + NonZeroU32::try_from(1).unwrap(), + ) + .unwrap(); + + let id = w.create_account(SEED, HD_INDEX, BIRTHDAY).await.unwrap(); + tracing::info!("Created account with id: {}", id); + + tracing::info!("Syncing wallet"); + w.sync(|scanned_to, tip| { + println!("Scanned: {}/{}", scanned_to, tip); + }) + .await + .unwrap(); + + tracing::info!("Syncing complete :)"); + + let summary = w.get_wallet_summary().unwrap(); + tracing::info!("Wallet summary: {:?}", summary); + + tracing::info!("Proposing a transaction"); + let addr = ZcashAddress::try_from_encoded("utest1z00xn09t4eyeqw9zmjss75sf460423dymgyfjn8rtlj26cffy0yad3eea82xekk24s00wnm38cvyrm2c6x7fxlc0ns4a5j7utgl6lchvglfvl9g9p56fqwzvzvj9d3z6r6ft88j654d7dj0ep6myq5duz9s8x78fdzmtx04d2qn8ydkxr4lfdhlkx9ktrw98gd97dateegrr68vl8xu"); + + w.transfer(SEED, 0, addr.unwrap(), 1000).await.unwrap(); + tracing::info!("Transaction proposed"); + + let summary = w.get_wallet_summary().unwrap(); + tracing::info!("Wallet summary: {:?}", summary); +}