Skip to content

Commit 04c6957

Browse files
committed
refactor: add strategy swaps
1 parent 5ccd956 commit 04c6957

File tree

16 files changed

+1250
-295
lines changed

16 files changed

+1250
-295
lines changed

src/bin/bitmaskd.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use bitcoin_30::secp256k1::{ecdh::SharedSecret, PublicKey, SecretKey};
2525
use bitmask_core::{
2626
bitcoin::{save_mnemonic, sign_and_publish_psbt_file},
2727
carbonado::{
28-
handle_file,
28+
handle_file, marketplace_retrieve, marketplace_store,
2929
metrics::{metrics, metrics_csv},
30-
server_retrieve, server_store, store,
30+
store,
3131
},
3232
constants::{
3333
get_marketplace_nostr_key, get_marketplace_seed, get_network, get_udas_utxo, switch_network,
@@ -524,7 +524,7 @@ async fn co_server_store(
524524
body: Bytes,
525525
) -> Result<impl IntoResponse, AppError> {
526526
info!("POST /carbonado/server/{name}, {} bytes", body.len());
527-
let (filepath, encoded) = server_store(&name, &body, None).await?;
527+
let (filepath, encoded) = marketplace_store(&name, &body, None).await?;
528528

529529
match OpenOptions::new()
530530
.read(true)
@@ -624,7 +624,7 @@ async fn co_metadata(
624624
async fn co_server_retrieve(Path(name): Path<String>) -> Result<impl IntoResponse, AppError> {
625625
info!("GET /server/{name}");
626626

627-
let result = server_retrieve(&name).await;
627+
let result = marketplace_retrieve(&name).await;
628628
let cc = CacheControl::new().with_no_cache();
629629

630630
match result {
@@ -684,6 +684,56 @@ async fn rgb_proxy_media_data_save(
684684
Ok((StatusCode::OK, Json(resp)))
685685
}
686686

687+
async fn rgb_auction_get_offer(
688+
Path(offer_id): Path<String>,
689+
Json(_request): Json<String>,
690+
) -> Result<impl IntoResponse, AppError> {
691+
info!("GET /auction/{offer_id}");
692+
Ok((StatusCode::OK, Json("")))
693+
}
694+
695+
async fn rgb_auction_create_offer(
696+
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
697+
Path(offer_id): Path<String>,
698+
Json(_request): Json<String>,
699+
) -> Result<impl IntoResponse, AppError> {
700+
info!("POST /auction/{offer_id}");
701+
Ok((StatusCode::OK, Json("")))
702+
}
703+
704+
async fn rgb_auction_destroy_offer(
705+
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
706+
Path(offer_id): Path<String>,
707+
) -> Result<impl IntoResponse, AppError> {
708+
info!("DELETE /auction/{offer_id}");
709+
Ok((StatusCode::OK, Json("")))
710+
}
711+
712+
async fn rgb_auction_get_bid(
713+
Path((offer_id, bid_id)): Path<(String, String)>,
714+
Json(_request): Json<String>,
715+
) -> Result<impl IntoResponse, AppError> {
716+
info!("GET /auction/{offer_id}/{bid_id}");
717+
Ok((StatusCode::OK, Json("")))
718+
}
719+
720+
async fn rgb_auction_create_bid(
721+
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
722+
Path((offer_id, bid_id)): Path<(String, String)>,
723+
Json(_request): Json<String>,
724+
) -> Result<impl IntoResponse, AppError> {
725+
info!("POST /auction/{offer_id}/{bid_id}");
726+
Ok((StatusCode::OK, Json("")))
727+
}
728+
729+
async fn rgb_auction_destroy_bid(
730+
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
731+
Path((offer_id, bid_id)): Path<(String, String)>,
732+
) -> Result<impl IntoResponse, AppError> {
733+
info!("DELETE /auction/{offer_id}/{bid_id}");
734+
Ok((StatusCode::OK, Json("")))
735+
}
736+
687737
const BMC_VERSION: &str = env!("CARGO_PKG_VERSION");
688738

689739
async fn status() -> Result<impl IntoResponse, AppError> {
@@ -822,6 +872,18 @@ async fn main() -> Result<()> {
822872
.route("/proxy/media-metadata", post(rgb_proxy_media_data_save))
823873
.route("/proxy/media-metadata/:id", get(rgb_proxy_media_retrieve))
824874
.route("/proxy/media/:id", get(rgb_proxy_metadata_retrieve))
875+
.route("/auctions/:offer_id", get(rgb_auction_get_offer))
876+
.route("/auctions/:offer_id", post(rgb_auction_create_offer))
877+
.route("/auctions/:offer_id", delete(rgb_auction_destroy_offer))
878+
.route("/auctions/:offer_id/bid/:bid_id", get(rgb_auction_get_bid))
879+
.route(
880+
"/auctions/:offer_id/bid/:bid_id",
881+
post(rgb_auction_create_bid),
882+
)
883+
.route(
884+
"/auction/:offer_id/bid/:bid_id",
885+
delete(rgb_auction_destroy_bid),
886+
)
825887
.route("/metrics.json", get(json_metrics))
826888
.route("/metrics.csv", get(csv_metrics));
827889

src/bitcoin/payment.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ pub async fn create_payjoin(
9393
.into_iter()
9494
.enumerate()
9595
.find(|(_, txo)| {
96-
invoices.iter().all(|invoice| {
97-
txo.script_pubkey != invoice.address.script_pubkey()
98-
})
96+
invoices
97+
.iter()
98+
.all(|invoice| txo.script_pubkey != invoice.address.script_pubkey())
9999
})
100100
.map(|(i, _)| i);
101101

src/bitcoin/psbt.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use crate::{
99

1010
#[derive(Error, Debug)]
1111
pub enum BitcoinPsbtError {
12+
/// Could not broadcast PSBT
13+
#[error("Could not broadcast PSBT")]
14+
CouldNotBroadcastPsbt(String),
1215
/// Could not finalize when signing PSBT
1316
#[error("Could not finalize when signing PSBT")]
1417
CouldNotFinalizePsbt,
@@ -70,7 +73,10 @@ pub async fn publish_psbt(
7073
let tx = psbt.extract_tx();
7174
debug!("tx:", &serialize(&tx.clone()).to_hex());
7275
let blockchain = get_blockchain().await;
73-
blockchain.broadcast(&tx).await?;
76+
blockchain
77+
.broadcast(&tx)
78+
.await
79+
.map_err(|op| BitcoinPsbtError::CouldNotBroadcastPsbt(op.to_string()))?;
7480

7581
let txid = tx.txid();
7682
let tx = blockchain.get_tx(&txid).await?;

src/carbonado.rs

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,24 @@ pub mod error;
99
pub mod metrics;
1010

1111
#[cfg(not(target_arch = "wasm32"))]
12-
pub use server::{handle_file, retrieve, retrieve_metadata, server_retrieve, server_store, store};
12+
pub use server::{
13+
auctions_retrieve, auctions_store, handle_file, marketplace_retrieve, marketplace_store,
14+
retrieve, retrieve_metadata, store,
15+
};
1316

1417
#[cfg(not(target_arch = "wasm32"))]
1518
mod server {
16-
use crate::constants::get_marketplace_nostr_key;
19+
use crate::constants::{get_coordinator_nostr_key, get_marketplace_nostr_key};
1720

1821
use super::*;
1922

2023
use std::{
2124
io::{Error, ErrorKind},
2225
path::PathBuf,
26+
str::FromStr,
2327
};
2428

29+
use bitcoin_30::secp256k1::ecdh::SharedSecret;
2530
use tokio::fs;
2631

2732
pub async fn store(
@@ -51,7 +56,7 @@ mod server {
5156
Ok(())
5257
}
5358

54-
pub async fn server_store(
59+
pub async fn marketplace_store(
5560
name: &str,
5661
input: &[u8],
5762
metadata: Option<Vec<u8>>,
@@ -78,6 +83,37 @@ mod server {
7883
Ok((filepath, body))
7984
}
8085

86+
pub async fn auctions_store(
87+
bundle_id: &str,
88+
name: &str,
89+
input: &[u8],
90+
metadata: Option<Vec<u8>>,
91+
) -> Result<(PathBuf, Vec<u8>), CarbonadoError> {
92+
let coordinator_key: String = get_coordinator_nostr_key().await;
93+
94+
let level = 15;
95+
let sk = hex::decode(coordinator_key)?;
96+
let secret_key = SecretKey::from_slice(&sk)?;
97+
let public_key =
98+
PublicKey::from_str(bundle_id).map_err(|_| CarbonadoError::WrongNostrPublicKey)?;
99+
100+
let share_sk = SharedSecret::new(&public_key, &secret_key);
101+
let pk = share_sk.secret_bytes();
102+
let pk_hex = hex::encode(pk);
103+
104+
let mut meta: Option<[u8; 8]> = default!();
105+
if let Some(metadata) = metadata {
106+
let mut inner: [u8; 8] = default!();
107+
inner[..metadata.len()].copy_from_slice(&metadata);
108+
meta = Some(inner);
109+
}
110+
111+
let (body, _encode_info) = carbonado::file::encode(&sk, Some(&pk), input, level, meta)?;
112+
let filepath = handle_file(&pk_hex, name, body.len()).await?;
113+
fs::write(filepath.clone(), body.clone()).await?;
114+
Ok((filepath, body))
115+
}
116+
81117
pub async fn retrieve(
82118
sk: &str,
83119
name: &str,
@@ -120,7 +156,9 @@ mod server {
120156
Ok((Vec::new(), None))
121157
}
122158

123-
pub async fn server_retrieve(name: &str) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
159+
pub async fn marketplace_retrieve(
160+
name: &str,
161+
) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
124162
let marketplace_key: String = get_marketplace_nostr_key().await;
125163

126164
let sk = hex::decode(marketplace_key)?;
@@ -144,6 +182,37 @@ mod server {
144182
Ok((Vec::new(), None))
145183
}
146184

185+
pub async fn auctions_retrieve(
186+
bundle_id: &str,
187+
name: &str,
188+
) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
189+
let coordinator_key: String = get_coordinator_nostr_key().await;
190+
191+
let sk = hex::decode(coordinator_key)?;
192+
let secret_key = SecretKey::from_slice(&sk)?;
193+
let public_key =
194+
PublicKey::from_str(bundle_id).map_err(|_| CarbonadoError::WrongNostrPublicKey)?;
195+
196+
let share_sk = SharedSecret::new(&public_key, &secret_key);
197+
let pk = share_sk.secret_bytes();
198+
let pk = hex::encode(pk);
199+
200+
let mut final_name = name.to_string();
201+
let network = NETWORK.read().await.to_string();
202+
let networks = ["bitcoin", "testnet", "signet", "regtest"];
203+
if !networks.into_iter().any(|x| name.contains(x)) {
204+
final_name = format!("{network}-{name}");
205+
}
206+
207+
let filepath = handle_file(&pk, &final_name, 0).await?;
208+
if let Ok(bytes) = fs::read(filepath).await {
209+
let (header, decoded) = carbonado::file::decode(&sk, &bytes)?;
210+
return Ok((decoded, header.metadata.map(|m| m.to_vec())));
211+
}
212+
213+
Ok((Vec::new(), None))
214+
}
215+
147216
pub async fn handle_file(
148217
pk: &str,
149218
name: &str,
@@ -210,7 +279,10 @@ mod server {
210279
}
211280

212281
#[cfg(target_arch = "wasm32")]
213-
pub use client::{retrieve, retrieve_metadata, server_retrieve, server_store, store};
282+
pub use client::{
283+
auctions_retrieve, auctions_store, marketplace_retrieve, marketplace_store, retrieve,
284+
retrieve_metadata, store,
285+
};
214286

215287
#[cfg(target_arch = "wasm32")]
216288
mod client {
@@ -296,7 +368,7 @@ mod client {
296368
}
297369
}
298370

299-
pub async fn server_store(
371+
pub async fn marketplace_store(
300372
name: &str,
301373
input: &[u8],
302374
_metadata: Option<Vec<u8>>,
@@ -328,6 +400,15 @@ mod client {
328400
}
329401
}
330402

403+
pub async fn auctions_store(
404+
_bundle_id: &str,
405+
_name: &str,
406+
_input: &[u8],
407+
_metadata: Option<Vec<u8>>,
408+
) -> Result<(), CarbonadoError> {
409+
todo!()
410+
}
411+
331412
pub async fn retrieve_metadata(sk: &str, name: &str) -> Result<FileMetadata, CarbonadoError> {
332413
let sk = hex::decode(sk)?;
333414
let secret_key = SecretKey::from_slice(&sk)?;
@@ -416,7 +497,9 @@ mod client {
416497
Ok((Vec::new(), None))
417498
}
418499

419-
pub async fn server_retrieve(name: &str) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
500+
pub async fn marketplace_retrieve(
501+
name: &str,
502+
) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
420503
let network = NETWORK.read().await.to_string();
421504
let endpoints = CARBONADO_ENDPOINT.read().await.to_string();
422505
let endpoints: Vec<&str> = endpoints.split(',').collect();
@@ -438,6 +521,13 @@ mod client {
438521
Ok((encoded.to_vec(), None))
439522
}
440523

524+
pub async fn auctions_retrieve(
525+
_bundle_id: &str,
526+
_name: &str,
527+
) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
528+
todo!()
529+
}
530+
441531
async fn fetch_post(url: String, body: Arc<Vec<u8>>) -> Result<JsValue, JsValue> {
442532
let array = Uint8Array::new_with_length(body.len() as u32);
443533
array.copy_from(&body);

src/carbonado/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub enum CarbonadoError {
2727
AllEndpointsFailed,
2828
/// Wrong Nostr private key
2929
WrongNostrPrivateKey,
30+
/// Wrong Nostr public key
31+
WrongNostrPublicKey,
3032
/// Debug: {0}
3133
Debug(String),
3234
}

src/constants.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ pub async fn get_marketplace_fee_xpub() -> String {
7676
MARKETPLACE_FEE_XPUB.read().await.to_string()
7777
}
7878

79+
pub async fn get_coordinator_nostr_key() -> String {
80+
MARKETPLACE_NOSTR.read().await.to_string()
81+
}
82+
7983
pub static UDAS_UTXO: Lazy<RwLock<String>> = Lazy::new(|| RwLock::new(dot_env("UDAS_UTXO")));
8084

8185
pub async fn get_udas_utxo() -> String {
@@ -220,5 +224,4 @@ pub mod storage_keys {
220224
pub const ASSETS_OFFERS: &str = "bitmask-asset_offers.c15";
221225
pub const ASSETS_BIDS: &str = "bitmask-asset_bids.c15";
222226
pub const MARKETPLACE_OFFERS: &str = "bitmask-marketplace_public_offers.c15";
223-
pub const MARKETPLACE_BIDS: &str = "bitmask-marketplace_public_bids.c15";
224227
}

0 commit comments

Comments
 (0)