Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/development' into HB/rbf
Browse files Browse the repository at this point in the history
  • Loading branch information
josediegorobles committed Dec 26, 2023
2 parents 86f7928 + 11edf38 commit d36aa4a
Show file tree
Hide file tree
Showing 10 changed files with 1,937 additions and 368 deletions.
52 changes: 43 additions & 9 deletions lib/web/rgb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,6 @@ export const createOffer = async (
): Promise<RgbOfferResponse> =>
JSON.parse(await BMC.create_offer(nostrHexSk, request));

export const createAuctionBid = async (
nostrHexSk: string,
request: RgbAuctionBidRequest
): Promise<RgbAuctionBidResponse> =>
JSON.parse(await BMC.create_auction_bid(nostrHexSk, request));

export const createBid = async (
nostrHexSk: string,
request: RgbBidRequest
Expand All @@ -175,11 +169,24 @@ export const createSwap = async (
): Promise<RgbSwapResponse> =>
JSON.parse(await BMC.create_swap(nostrHexSk, request));

export const createAuctionOffer = async (
nostrHexSk: string,
request: RgbAuctionOfferRequest
): Promise<RgbAuctionBidResponse> =>
JSON.parse(await BMC.create_auction_offers(nostrHexSk, request));


export const createAuctionBid = async (
nostrHexSk: string,
request: RgbAuctionBidRequest
): Promise<RgbAuctionBidResponse> =>
JSON.parse(await BMC.create_auction_bid(nostrHexSk, request));

export const finishAuction = async (
nostrHexSk: string,
request: string
): Promise<RgbAuctionOfferResponse[]> =>
JSON.parse(await BMC.finish_auction(nostrHexSk, request));
JSON.parse(await BMC.finish_auction_offers(nostrHexSk, request));

export const listAuctions = async (): Promise<RgbOffersResponse> =>
JSON.parse(await BMC.list_auctions());
Expand Down Expand Up @@ -817,11 +824,38 @@ export enum RgbSwapStrategy {
P2P = "p2p",
HotSwap = "hotswap",
}

export interface RgbAuctionStrategy {
auction?: string,
airdrop?: string,
}

export interface RgbAuctionOfferRequest {
offers: RgbOfferRequest[],

signKeys: string[],

/// List of Offers
offers: RgbOfferRequest[],
strategy: RgbAuctionStrategy,

fee?: PsbtFeeRequest
}

export interface RgbOfferUpdateRequest {
/// The Contract ID
contract_id: string,
/// The Offer ID
offer_id: string,
// Swap PSBT
offer_psbt: string
}

export interface RgbOfferUpdateResponse {
/// The Contract ID
contract_id: string,
/// The Offer ID
offer_id: string,
/// Updated?
updated: boolean
}

export interface RgbAuctionBidRequest {
Expand Down
120 changes: 65 additions & 55 deletions src/bin/bitmaskd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ use axum::{
use bitcoin_30::secp256k1::{ecdh::SharedSecret, PublicKey, SecretKey};
use bitmask_core::{
bitcoin::{save_mnemonic, sign_and_publish_psbt_file},
carbonado::{handle_file, marketplace_retrieve, marketplace_store, metrics, store},
carbonado::{
auctions_retrieve, auctions_store, handle_file, marketplace_retrieve, marketplace_store,
metrics, store,
},
constants::{
get_marketplace_nostr_key, get_marketplace_seed, get_network, get_udas_utxo, switch_network,
},
Expand All @@ -34,11 +37,12 @@ use bitmask_core::{
proxy_media_data_store, proxy_media_retrieve, proxy_metadata_retrieve,
},
rgb::{
accept_transfer, clear_watcher as rgb_clear_watcher, create_invoice, create_psbt,
create_watcher, full_transfer_asset, get_contract, import as rgb_import, issue_contract,
list_contracts, list_interfaces, list_schemas, list_transfers as list_rgb_transfers,
reissue_contract, remove_transfer as remove_rgb_transfer,
save_transfer as save_rgb_transfer,
accept_transfer,
carbonado::retrieve_auctions_offers,
clear_watcher as rgb_clear_watcher, create_invoice, create_psbt, create_watcher,
full_transfer_asset, get_contract, import as rgb_import, issue_contract, list_contracts,
list_interfaces, list_schemas, list_transfers as list_rgb_transfers, reissue_contract,
remove_transfer as remove_rgb_transfer, save_transfer as save_rgb_transfer,
structs::{
RgbProxyConsigCarbonadoReq, RgbProxyConsigFileReq, RgbProxyConsigUpload,
RgbProxyMediaCarbonadoReq, RgbProxyMediaFileReq,
Expand Down Expand Up @@ -687,53 +691,68 @@ async fn rgb_proxy_media_data_save(
Ok((StatusCode::OK, Json(resp)))
}

async fn rgb_auction_get_offer(
Path(offer_id): Path<String>,
Json(_request): Json<String>,
async fn rgb_retrieve_auction(
Path((bundle_id, name)): Path<(String, String)>,
) -> Result<impl IntoResponse, AppError> {
info!("GET /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
}
info!("GET /auction/{bundle_id}");

async fn rgb_auction_create_offer(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path(offer_id): Path<String>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("POST /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
let result = auctions_retrieve(&bundle_id, &name).await;
let cc = CacheControl::new().with_no_cache();
match result {
Ok((bytes, _)) => {
debug!("read {0} bytes.", bytes.len());
Ok((StatusCode::OK, TypedHeader(cc), bytes))
}
Err(e) => {
debug!("file read error {0} .Details: {1}.", name, e.to_string());
Ok((StatusCode::OK, TypedHeader(cc), Vec::<u8>::new()))
}
}
}

async fn rgb_auction_destroy_offer(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path(offer_id): Path<String>,
async fn rgb_store_auction(
Path((bundle_id, name)): Path<(String, String)>,
body: Bytes,
) -> Result<impl IntoResponse, AppError> {
info!("DELETE /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
}
info!("POST /auction/{bundle_id}");
let (filepath, encoded) = auctions_store(&bundle_id, &name, &body, None).await?;

async fn rgb_auction_get_bid(
Path((offer_id, bid_id)): Path<(String, String)>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("GET /auction/{offer_id}/{bid_id}");
Ok((StatusCode::OK, Json("")))
}
match OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&filepath)
{
Ok(file) => {
let present_header = match carbonado::file::Header::try_from(&file) {
Ok(header) => header,
_ => carbonado::file::Header::try_from(&body)?,
};
let present_len = present_header.encoded_len - present_header.padding_len;
debug!("present_len: {present_len}");
let resp = fs::write(&filepath, &encoded).await;
debug!("file override status {}", resp.is_ok());
}
Err(err) => match err.kind() {
ErrorKind::NotFound => {
debug!("no file found, writing 0 bytes.");
fs::write(&filepath, &body).await?;
}
_ => {
error!("error in POST /carbonado/server/{name}: {err}");
return Err(err.into());
}
},
}

async fn rgb_auction_create_bid(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path((offer_id, bid_id)): Path<(String, String)>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("POST /auction/{offer_id}/{bid_id}");
Ok((StatusCode::OK, Json("")))
let cc = CacheControl::new().with_no_cache();
Ok((StatusCode::OK, TypedHeader(cc)))
}

async fn rgb_auction_destroy_bid(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path((offer_id, bid_id)): Path<(String, String)>,
async fn rgb_destroy_auction(
Path((bundle_id, _name)): Path<(String, String)>,
) -> Result<impl IntoResponse, AppError> {
info!("DELETE /auction/{offer_id}/{bid_id}");
info!("DELETE /auction/{bundle_id}");
Ok((StatusCode::OK, Json("")))
}

Expand Down Expand Up @@ -862,18 +881,9 @@ async fn main() -> Result<()> {
.route("/proxy/media-metadata", post(rgb_proxy_media_data_save))
.route("/proxy/media-metadata/:id", get(rgb_proxy_media_retrieve))
.route("/proxy/media/:id", get(rgb_proxy_metadata_retrieve))
.route("/auctions/:offer_id", get(rgb_auction_get_offer))
.route("/auctions/:offer_id", post(rgb_auction_create_offer))
.route("/auctions/:offer_id", delete(rgb_auction_destroy_offer))
.route("/auctions/:offer_id/bid/:bid_id", get(rgb_auction_get_bid))
.route(
"/auctions/:offer_id/bid/:bid_id",
post(rgb_auction_create_bid),
)
.route(
"/auction/:offer_id/bid/:bid_id",
delete(rgb_auction_destroy_bid),
)
.route("/auction/:bundle_id/:name", get(rgb_retrieve_auction))
.route("/auction/:bundle_id/:name", post(rgb_store_auction))
.route("/auction/:bundle_id/:name", delete(rgb_destroy_auction))
.route("/metrics.json", get(json_metrics))
.route("/metrics.csv", get(csv_metrics));

Expand Down
58 changes: 50 additions & 8 deletions src/carbonado.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ mod client {
use gloo_net::http::Request;
use gloo_utils::errors::JsError;

use crate::constants::CARBONADO_ENDPOINT;
use crate::constants::{BITMASK_ENDPOINT, CARBONADO_ENDPOINT};

fn js_to_error(js_value: JsValue) -> CarbonadoError {
CarbonadoError::JsError(js_to_js_error(js_value))
Expand Down Expand Up @@ -414,12 +414,36 @@ mod client {
}

pub async fn auctions_store(
_bundle_id: &str,
_name: &str,
_input: &[u8],
bundle_id: &str,
name: &str,
input: &[u8],
_metadata: Option<Vec<u8>>,
) -> Result<(), CarbonadoError> {
todo!()
let body = Arc::new(input.to_vec());
let network = NETWORK.read().await.to_string();
let endpoints = BITMASK_ENDPOINT.read().await.to_string();
let endpoints: Vec<&str> = endpoints.split(',').collect();
let requests = Array::new();

for endpoint in endpoints {
let url = format!("{endpoint}/auction/{bundle_id}/{network}-{name}");
let fetch_fn = future_to_promise(fetch_post(url, body.clone()));
requests.push(&fetch_fn);
}

let results = JsFuture::from(Promise::all_settled(&JsValue::from(requests)))
.await
.map_err(js_to_error)?;

info!(format!("Store results: {results:?}"));

let results = serde_wasm_bindgen::from_value::<Vec<PostStorePromiseResult>>(results)?;
let success = results.iter().any(|result| result.value == 200.0);
if success {
Ok(())
} else {
Err(CarbonadoError::AllEndpointsFailed)
}
}

pub async fn retrieve_metadata(sk: &str, name: &str) -> Result<FileMetadata, CarbonadoError> {
Expand Down Expand Up @@ -535,10 +559,28 @@ mod client {
}

pub async fn auctions_retrieve(
_bundle_id: &str,
_name: &str,
bundle_id: &str,
name: &str,
) -> Result<(Vec<u8>, Option<Vec<u8>>), CarbonadoError> {
todo!()
let network = NETWORK.read().await.to_string();
let endpoints = BITMASK_ENDPOINT.read().await.to_string();
let endpoints: Vec<&str> = endpoints.split(',').collect();

let requests = Array::new();
for endpoint in endpoints.iter() {
let url = format!("{endpoint}/auction/{bundle_id}/{network}-{name}");
let fetch_fn = future_to_promise(fetch_get_byte_array(url));
requests.push(&fetch_fn);
}

let result = JsFuture::from(Promise::any(&JsValue::from(requests)))
.await
.map_err(js_to_error)?;

let array = Uint8Array::from(result);
let encoded = array.to_vec();

Ok((encoded.to_vec(), None))
}

async fn fetch_post(url: String, body: Arc<Vec<u8>>) -> Result<JsValue, JsValue> {
Expand Down
Loading

0 comments on commit d36aa4a

Please sign in to comment.