diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index fa3bc1e..7e429cd 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -54,7 +54,7 @@ jobs: BITCOIN_NETWORK_NAME: regtest run: | cargo install cargo-tarpaulin - cargo tarpaulin --release --out Xml + cargo tarpaulin --release --out xml - name: Upload to Codecov uses: codecov/codecov-action@v3 diff --git a/Cargo.toml b/Cargo.toml index f467d57..8baa610 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ actix-cors = "0.6.4" actix-files = "0.6.2" clap = { version = "4.0.15", features = ["derive", "env"] } rand = "0.8.5" -rgb-lib = "=0.2.0-alpha.2" +rgb-lib = "0.2.0-alpha.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/src/main.rs b/src/main.rs index ab04f4f..fabf336 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,6 +70,8 @@ mod tests { pub static PROXY_ENDPOINT: Lazy = Lazy::new(|| "rpc://127.0.0.1:3000/json-rpc".to_string()); + pub static MIN_CONFIRMATIONS: u8 = 1; + #[derive(Serialize, Deserialize)] pub struct OnlineResult { pub id: String, diff --git a/src/opts.rs b/src/opts.rs index 691b1f3..4622acf 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -137,10 +137,13 @@ pub fn get_wallet_data() -> rgb_lib::wallet::WalletData { panic!("Internal error: an wrong args.database_type should be checked in the parser.") }; + let max_allocations_per_utxo = 1; + WalletData { data_dir: args.data_dir, bitcoin_network, database_type, + max_allocations_per_utxo, pubkey: "".to_string(), mnemonic: None, } diff --git a/src/wallet.rs b/src/wallet.rs index 7fab00c..e29b7ef 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -77,6 +77,7 @@ pub async fn put( data_dir: base_data.data_dir, bitcoin_network: base_data.bitcoin_network, database_type: base_data.database_type, + max_allocations_per_utxo: base_data.max_allocations_per_utxo, pubkey: params.pubkey.clone(), mnemonic: Some(params.mnemonic.clone()), }; diff --git a/src/wallet/assets.rs b/src/wallet/assets.rs index 8d659f8..14fe476 100644 --- a/src/wallet/assets.rs +++ b/src/wallet/assets.rs @@ -1,13 +1,13 @@ use crate::{wallet::Balance, ShiroWallet}; use actix_web::{put, web, HttpResponse, Responder}; -use rgb_lib::wallet::AssetIface; +use rgb_lib::AssetSchema; use serde::Deserialize; use serde::Serialize; use std::sync::Mutex; #[derive(Deserialize, Serialize)] pub struct AssetsParams { - filter_asset_types: Vec, + filter_asset_types: Vec, } #[derive(Deserialize, Serialize)] @@ -34,8 +34,8 @@ pub struct AssetRgb20 { balance: Balance, } -impl From for AssetRgb20 { - fn from(origin: rgb_lib::wallet::AssetRgb20) -> AssetRgb20 { +impl From for AssetRgb20 { + fn from(origin: rgb_lib::wallet::AssetNIA) -> AssetRgb20 { AssetRgb20 { asset_id: origin.asset_id, ticker: origin.ticker, @@ -56,8 +56,8 @@ pub struct AssetRgb25 { data_paths: Vec, } -impl From for AssetRgb25 { - fn from(origin: rgb_lib::wallet::AssetRgb25) -> AssetRgb25 { +impl From for AssetRgb25 { + fn from(origin: rgb_lib::wallet::AssetCFA) -> AssetRgb25 { AssetRgb25 { asset_id: origin.asset_id, name: origin.name, @@ -82,12 +82,12 @@ pub struct Assets { impl From for Assets { fn from(x: rgb_lib::wallet::Assets) -> Assets { Assets { - rgb20: x.rgb20.map(|vec| { + rgb20: x.nia.map(|vec| { vec.into_iter() .map(AssetRgb20::from) .collect::>() }), - rgb25: x.rgb25.map(|vec| { + rgb25: x.cfa.map(|vec| { vec.into_iter() .map(AssetRgb25::from) .collect::>() diff --git a/src/wallet/blind.rs b/src/wallet/blind.rs index 9ccf376..61d1625 100644 --- a/src/wallet/blind.rs +++ b/src/wallet/blind.rs @@ -10,6 +10,7 @@ pub struct BlindParams { amount: Option, duration_seconds: Option, transport_endpoints: Vec, + min_confirmations: u8, } pub struct BlindParamsForLib { @@ -17,6 +18,7 @@ pub struct BlindParamsForLib { amount: Option, duration_seconds: Option, transport_endpoints: Vec, + min_confirmations: u8, } impl From for BlindParamsForLib { @@ -26,30 +28,29 @@ impl From for BlindParamsForLib { amount: x.amount.map(|str| str.parse::().unwrap()), duration_seconds: x.duration_seconds, transport_endpoints: x.transport_endpoints, + min_confirmations: x.min_confirmations, } } } #[derive(Serialize, Deserialize)] -pub struct BlindData { +pub struct ReceiveData { invoice: String, - blinded_utxo: String, - blinding_secret: String, + recipient_id: String, expiration_timestamp: Option, } -impl From for BlindData { - fn from(x: rgb_lib::wallet::BlindData) -> BlindData { - BlindData { +impl From for ReceiveData { + fn from(x: rgb_lib::wallet::ReceiveData) -> ReceiveData { + ReceiveData { invoice: x.invoice, - blinded_utxo: x.blinded_utxo, - blinding_secret: x.blinding_secret.to_string(), + recipient_id: x.recipient_id, expiration_timestamp: x.expiration_timestamp.map(|x| x.to_string()), } } } -#[put("/wallet/blind")] +#[put("/wallet/blind_receive")] pub async fn put( params: web::Json, data: web::Data>, @@ -57,17 +58,18 @@ pub async fn put( if data.lock().unwrap().wallet.is_some() { match actix_web::rt::task::spawn_blocking(move || { let params = BlindParamsForLib::from(params.clone()); - data.lock().unwrap().wallet.as_mut().unwrap().blind( + data.lock().unwrap().wallet.as_mut().unwrap().blind_receive( params.asset_id.clone(), params.amount, params.duration_seconds, params.transport_endpoints, + params.min_confirmations, ) }) .await .unwrap() { - Ok(blind_data) => HttpResponse::Ok().json(BlindData::from(blind_data)), + Ok(receive_data) => HttpResponse::Ok().json(ReceiveData::from(receive_data)), Err(e) => HttpResponse::BadRequest().body(e.to_string()), } } else { @@ -79,7 +81,7 @@ pub async fn put( mod tests { use super::*; - use crate::tests::PROXY_ENDPOINT; + use crate::tests::{MIN_CONFIRMATIONS, PROXY_ENDPOINT}; use crate::wallet::{ address::AddressResult, go_online::GoOnlineParams, @@ -138,7 +140,7 @@ mod tests { assert!(resp.status().is_success()); } { - let params = UtxosParams::new(true, Some(1), None, 1.0); + let params = UtxosParams::new(true, None, None, 1.0); let req = test::TestRequest::put() .uri("/wallet/utxos") .set_json(params) @@ -165,13 +167,18 @@ mod tests { amount: Some("10".to_string()), duration_seconds: Some(10), transport_endpoints: vec![PROXY_ENDPOINT.clone()], + min_confirmations: MIN_CONFIRMATIONS, }; let req = test::TestRequest::put() - .uri("/wallet/blind") + .uri("/wallet/blind_receive") .set_json(params) .to_request(); let resp = test::call_service(&app, req).await; println!("{:?}", resp); assert!(resp.status().is_success()); + let body: ReceiveData = test::read_body_json(resp).await; + assert!(body.invoice.starts_with("rgb:")); + assert!(body.recipient_id.starts_with("utxob:")); + assert!(body.expiration_timestamp.is_some()); } } diff --git a/src/wallet/invoice.rs b/src/wallet/invoice.rs index 7140901..97500b7 100644 --- a/src/wallet/invoice.rs +++ b/src/wallet/invoice.rs @@ -14,9 +14,10 @@ pub async fn put(params: web::Json) -> impl Responder { match decoded { Ok(invoice) => HttpResponse::Ok().json(InvoiceData { asset_iface: invoice.invoice_data().asset_iface, - blinded_utxo: invoice.invoice_data().blinded_utxo, + recipient_id: invoice.invoice_data().recipient_id, asset_id: invoice.invoice_data().asset_id, amount: invoice.invoice_data().amount, + network: invoice.invoice_data().network, expiration_timestamp: invoice.invoice_data().expiration_timestamp, transport_endpoints: invoice.invoice_data().transport_endpoints, }), @@ -46,7 +47,7 @@ mod tests { println!("{:?}", resp); assert!(resp.status().is_success()); let body: InvoiceData = test::read_body_json(resp).await; - let result = BlindedUTXO::new(body.blinded_utxo); + let result = BlindedUTXO::new(body.recipient_id); assert!(result.is_ok()); } diff --git a/src/wallet/issue/rgb20.rs b/src/wallet/issue/rgb20.rs index 04a0027..606dc1b 100644 --- a/src/wallet/issue/rgb20.rs +++ b/src/wallet/issue/rgb20.rs @@ -31,7 +31,7 @@ pub async fn put( match actix_web::rt::task::spawn_blocking(move || { let mut shiro_wallet = data.lock().unwrap(); let online = shiro_wallet.get_online().unwrap(); - shiro_wallet.wallet.as_mut().unwrap().issue_asset_rgb20( + shiro_wallet.wallet.as_mut().unwrap().issue_asset_nia( online, params.ticker.clone(), params.name.clone(), diff --git a/src/wallet/send.rs b/src/wallet/send.rs index 7beb1ed..e8a7d34 100644 --- a/src/wallet/send.rs +++ b/src/wallet/send.rs @@ -1,5 +1,6 @@ use crate::ShiroWallet; use actix_web::{post, web, HttpResponse, Responder}; +use rgb_lib::wallet::RecipientData; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; @@ -10,11 +11,13 @@ pub struct SendParams { recipient_map: HashMap>, donation: bool, fee_rate: f32, + min_confirmations: u8, } #[derive(Serialize, Deserialize)] struct Recipient { - blinded_utxo: String, + // TODO switch `BlindedUTXO` or `WitnessData` + recipient_data: RecipientData, amount: String, transport_endpoints: Vec, } @@ -22,7 +25,7 @@ struct Recipient { impl Recipient { pub fn conv(&self) -> rgb_lib::wallet::Recipient { rgb_lib::wallet::Recipient { - blinded_utxo: self.blinded_utxo.clone(), + recipient_data: self.recipient_data.clone(), amount: str::parse::(&self.amount).unwrap(), transport_endpoints: self.transport_endpoints.clone(), } @@ -32,7 +35,7 @@ impl Recipient { impl From for Recipient { fn from(x: rgb_lib::wallet::Recipient) -> Recipient { Recipient { - blinded_utxo: x.blinded_utxo, + recipient_data: x.recipient_data, amount: x.amount.to_string(), transport_endpoints: x.transport_endpoints, } @@ -72,6 +75,7 @@ pub async fn post( recipient_map, params.donation, params.fee_rate, + params.min_confirmations, ) }) .await @@ -92,6 +96,7 @@ pub async fn post( mod tests { use super::*; + use crate::tests::MIN_CONFIRMATIONS; use crate::tests::PROXY_ENDPOINT; use crate::wallet::{ address::AddressResult, @@ -104,15 +109,18 @@ mod tests { use rgb_lib::{ generate_keys, wallet::{Wallet, WalletData}, + SecretSeal, }; + use std::str::FromStr; - async fn get_blinded_utxo() -> String { + async fn get_recipient_id() -> String { let keys = generate_keys(rgb_lib::BitcoinNetwork::Regtest); let base_data = shiro_backend::opts::get_wallet_data(); let wallet_data = WalletData { data_dir: base_data.data_dir, bitcoin_network: base_data.bitcoin_network, database_type: base_data.database_type, + max_allocations_per_utxo: 1, pubkey: keys.xpub, mnemonic: Some(keys.mnemonic), }; @@ -126,11 +134,17 @@ mod tests { wallet .create_utxos(online, true, Some(1), None, 1.0) .unwrap(); - let blind_data = wallet - .blind(None, None, None, vec![PROXY_ENDPOINT.clone()]) + let receive_data = wallet + .blind_receive( + None, + None, + None, + vec![PROXY_ENDPOINT.clone()], + MIN_CONFIRMATIONS, + ) .unwrap(); //let blind_data = wallet.blind(Some(asset_id), Some(10), None).unwrap(); - blind_data.blinded_utxo + receive_data.recipient_id }) .await .unwrap() @@ -207,12 +221,14 @@ mod tests { .to_request(); test::call_and_read_body_json(&app, req).await }; - let blinded_utxo = get_blinded_utxo().await; + let recipient_id = get_recipient_id().await; let mut recipient_map = HashMap::new(); recipient_map.insert( rgb20_result.asset_id, vec![Recipient { - blinded_utxo, + recipient_data: RecipientData::BlindedUTXO( + SecretSeal::from_str(&recipient_id).unwrap(), + ), amount: "10".to_string(), transport_endpoints: vec![PROXY_ENDPOINT.clone()], }], @@ -221,6 +237,7 @@ mod tests { recipient_map, donation: false, fee_rate: 1.0, + min_confirmations: MIN_CONFIRMATIONS, }; let req = test::TestRequest::post() .uri("/wallet/send") diff --git a/src/wallet/transfers.rs b/src/wallet/transfers.rs index c85227a..7ec7a41 100644 --- a/src/wallet/transfers.rs +++ b/src/wallet/transfers.rs @@ -1,7 +1,7 @@ use crate::ShiroWallet; use actix_web::{delete, put, web, HttpResponse, Responder}; use rgb_lib::{ - wallet::{Outpoint, TransferKind}, + wallet::{Outpoint, TransferKind, TransferTransportEndpoint}, TransferStatus, }; use serde::Deserialize; @@ -22,11 +22,11 @@ pub struct Transfer { amount: String, kind: String, txid: Option, - blinded_utxo: Option, - unblinded_utxo: Option, + recipient_id: Option, + receive_utxo: Option, change_utxo: Option, - blinding_secret: Option, expiration: Option, + transport_endpoints: Vec, } impl From for Transfer { @@ -45,16 +45,18 @@ impl From for Transfer { amount: x.amount.to_string(), kind: match x.kind { TransferKind::Issuance => "issuance", - TransferKind::Receive => "receive", + TransferKind::ReceiveBlind => "receive", + // FIXME + TransferKind::ReceiveWitness => "receive", TransferKind::Send => "send", } .to_string(), txid: x.txid, - blinded_utxo: x.blinded_utxo, - unblinded_utxo: x.unblinded_utxo, + recipient_id: x.recipient_id, + receive_utxo: x.receive_utxo, change_utxo: x.change_utxo, - blinding_secret: x.blinding_secret.map(|n| n.to_string()), expiration: x.expiration.map(|n| n.to_string()), + transport_endpoints: x.transport_endpoints, } } } diff --git a/src/wallet/unspents.rs b/src/wallet/unspents.rs index d963413..994bf7e 100644 --- a/src/wallet/unspents.rs +++ b/src/wallet/unspents.rs @@ -79,7 +79,8 @@ pub async fn put( .wallet .as_mut() .unwrap() - .list_unspents(params.settled_only) + // TODO Set `online` for syncing a wallet + .list_unspents(None, params.settled_only) }) .await .unwrap() diff --git a/test-mocks/docker-compose.yml b/test-mocks/docker-compose.yml index cbcd836..719d5e4 100644 --- a/test-mocks/docker-compose.yml +++ b/test-mocks/docker-compose.yml @@ -17,6 +17,6 @@ services: depends_on: - bitcoind proxy: - image: ghcr.io/grunch/rgb-proxy-server:0.1.0 + image: ghcr.io/grunch/rgb-proxy-server:0.2.0 ports: - 3000:3000