diff --git a/binding.h b/binding.h index 2546274..d7189a0 100644 --- a/binding.h +++ b/binding.h @@ -180,6 +180,10 @@ struct CResult_____c_char derive_zip32(uint8_t coin, bool has_address, uint32_t address); +struct CResult_u32 save_send_template(uint8_t coin, char *template_); + +struct CResult_u8 delete_send_template(uint8_t coin, uint32_t id); + bool has_cuda(void); bool has_metal(void); diff --git a/src/api/dart_ffi.rs b/src/api/dart_ffi.rs index 43fa19a..af18b55 100644 --- a/src/api/dart_ffi.rs +++ b/src/api/dart_ffi.rs @@ -12,6 +12,7 @@ use std::path::Path; use std::sync::Mutex; use tokio::sync::Semaphore; use zcash_primitives::transaction::builder::Progress; +use crate::template::SendTemplate; static mut POST_COBJ: Option = None; @@ -763,6 +764,30 @@ pub unsafe extern "C" fn derive_zip32( to_cresult_str(res()) } +#[no_mangle] +pub unsafe extern "C" fn save_send_template(coin: u8, template: *mut c_char) -> CResult { + from_c_str!(template); + let res = || { + let c = CoinConfig::get(coin); + let db = c.db()?; + let template: SendTemplate = serde_json::from_str(&template)?; + let id = db.store_template(&template)?; + Ok(id) + }; + to_cresult(res()) +} + +#[no_mangle] +pub unsafe extern "C" fn delete_send_template(coin: u8, id: u32) -> CResult { + let res = || { + let c = CoinConfig::get(coin); + let db = c.db()?; + db.delete_template(id)?; + Ok(0) + }; + to_cresult(res()) +} + #[no_mangle] pub unsafe extern "C" fn has_cuda() -> bool { crate::gpu::has_cuda() diff --git a/src/db.rs b/src/db.rs index 21d0aac..97f03ae 100644 --- a/src/db.rs +++ b/src/db.rs @@ -28,6 +28,7 @@ mod backup; mod migration; pub use backup::FullEncryptedBackup; +use crate::template::SendTemplate; #[allow(dead_code)] pub const DEFAULT_DB_PATH: &str = "zec.db"; @@ -1191,6 +1192,32 @@ impl DbAdapter { Ok(reqs) } + pub fn store_template(&self, t: &SendTemplate) -> anyhow::Result { + let id = if t.id == 0 { + self.connection.execute("INSERT INTO \ + send_templates(title, address, amount, fiat_amount, fee_included, fiat, include_reply_to, subject, body) \ + VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9)", + params![t.title, t.address, t.amount, t.fiat_amount, t.fee_included, t.fiat, + t.memo.include_reply_to, t.memo.subject, t.memo.body])?; + self.connection.last_insert_rowid() as u32 + } + else { + self.connection.execute("UPDATE send_templates SET \ + title=?1, address=?2, amount=?3, fiat_amount=?4, fee_included=?5, fiat=?6, include_reply_to=?7, subject=?8, body=?9 \ + WHERE id_send_template=?10", + params![t.title, t.address, t.amount, t.fiat_amount, t.fee_included, t.fiat, + t.memo.include_reply_to, t.memo.subject, t.memo.body, t.id])?; + t.id + }; + Ok(id) + } + + pub fn delete_template(&self, id: u32) -> anyhow::Result<()> { + self.connection.execute("DELETE FROM send_templates WHERE id_send_template=?1", + params![id])?; + Ok(()) + } + fn network(&self) -> &'static Network { let chain = get_coin_chain(self.coin_type); chain.network() diff --git a/src/db/migration.rs b/src/db/migration.rs index a9214c5..a8c79a1 100644 --- a/src/db/migration.rs +++ b/src/db/migration.rs @@ -34,7 +34,7 @@ pub fn reset_db(connection: &Connection) -> anyhow::Result<()> { Ok(()) } -const LATEST_VERSION: u32 = 5; +const LATEST_VERSION: u32 = 6; pub fn init_db(connection: &Connection, network: &Network, has_ua: bool) -> anyhow::Result<()> { connection.execute( @@ -267,6 +267,21 @@ pub fn init_db(connection: &Connection, network: &Network, has_ua: bool) -> anyh )?; } + if version < 6 { + connection.execute( + "CREATE TABLE IF NOT EXISTS send_templates ( + id_send_template INTEGER PRIMARY KEY, + title TEXT NOT NULL, + address TEXT NOT NULL, + amount INTEGER NOT NULL, + fiat_amount DECIMAL NOT NULL, + fee_included BOOL NOT NULL, + fiat TEXT, + include_reply_to BOOL NOT NULL, + subject TEXT NOT NULL, + body TEXT NOT NULL)", [])?; + } + if version != LATEST_VERSION { update_schema_version(connection, LATEST_VERSION)?; connection.cache_flush()?; diff --git a/src/lib.rs b/src/lib.rs index 9205c0e..17a8740 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,6 +100,7 @@ mod zip32; // mod wallet; /// accounts, sync, payments, etc. pub mod api; +pub mod template; #[cfg(feature = "ledger")] mod ledger; diff --git a/src/template.rs b/src/template.rs new file mode 100644 index 0000000..2ed6346 --- /dev/null +++ b/src/template.rs @@ -0,0 +1,20 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct ZMemo { + pub include_reply_to: bool, + pub subject: String, + pub body: String, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct SendTemplate { + pub id: u32, + pub title: String, + pub address: String, + pub amount: u64, + pub fiat_amount: f64, + pub fee_included: bool, + pub fiat: Option, + pub memo: ZMemo, +}