mirror of
https://github.com/creating2morrow/neveko.git
synced 2025-01-03 09:29:39 +00:00
add submit multisig api
This commit is contained in:
parent
84a7656616
commit
ffa625185a
13 changed files with 144 additions and 39 deletions
|
@ -3,7 +3,7 @@
|
|||
## Architecture
|
||||
|
||||
* gui
|
||||
* three internal mircoservers (auth, contact and message)
|
||||
* four internal mircoservers (auth, contact, market and message)
|
||||
* core code module and lmdb
|
||||
* one external i2p hidden service
|
||||
* jwt for internal auth, jwp for external
|
||||
|
@ -62,3 +62,7 @@
|
|||
* If contacts don't come back online before JWP expiration the message must be drafted again
|
||||
* It is primarily meant for handling connectivity issues or the edge case where a contact is
|
||||
is online during the `check status` but goes offline while the message is being drafted
|
||||
|
||||
## Market
|
||||
|
||||
WIP
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use crate::{
|
||||
db,
|
||||
models::*,
|
||||
utils,
|
||||
};
|
||||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
/// Create a new dispute
|
||||
|
|
|
@ -35,12 +35,6 @@ struct MultisigMessageData {
|
|||
orid: String,
|
||||
}
|
||||
|
||||
/*
|
||||
TODOs(c2m):
|
||||
- API to valid payment and import multisig info
|
||||
- API to sign and submit the signed tx set
|
||||
*/
|
||||
|
||||
/// Create a new message
|
||||
pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Message {
|
||||
let rnd = utils::generate_rnd();
|
||||
|
|
|
@ -40,6 +40,7 @@ enum RpcFields {
|
|||
Open,
|
||||
Prepare,
|
||||
SignMultisig,
|
||||
SubmitMultisig,
|
||||
SweepAll,
|
||||
Transfer,
|
||||
ValidateAddress,
|
||||
|
@ -67,6 +68,7 @@ impl RpcFields {
|
|||
RpcFields::Open => String::from("open_wallet"),
|
||||
RpcFields::Prepare => String::from("prepare_multisig"),
|
||||
RpcFields::SignMultisig => String::from("sign_multisig"),
|
||||
RpcFields::SubmitMultisig => String::from("submit_multisig"),
|
||||
RpcFields::SweepAll => String::from("sweep_all"),
|
||||
RpcFields::Transfer => String::from("transfer"),
|
||||
RpcFields::ValidateAddress => String::from("validate_address"),
|
||||
|
@ -687,6 +689,37 @@ pub async fn sign_multisig(tx_data_hex: String) -> reqres::XmrRpcSignMultisigRes
|
|||
}
|
||||
}
|
||||
|
||||
/// Performs the xmr rpc 'submit_multisig' method
|
||||
pub async fn submit_multisig(tx_data_hex: String) -> reqres::XmrRpcSubmitMultisigResponse {
|
||||
info!("executing {}", RpcFields::SubmitMultisig.value());
|
||||
let client = reqwest::Client::new();
|
||||
let host = get_rpc_host();
|
||||
let params = reqres::XmrRpcSignMultisigParams { tx_data_hex };
|
||||
let req = reqres::XmrRpcSignMultisigRequest {
|
||||
jsonrpc: RpcFields::JsonRpcVersion.value(),
|
||||
id: RpcFields::Id.value(),
|
||||
method: RpcFields::SubmitMultisig.value(),
|
||||
params,
|
||||
};
|
||||
let login: RpcLogin = get_rpc_creds();
|
||||
match client
|
||||
.post(host)
|
||||
.json(&req)
|
||||
.send_with_digest_auth(&login.username, &login.credential)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let res = response.json::<reqres::XmrRpcSubmitMultisigResponse>().await;
|
||||
debug!("{} response: {:?}", RpcFields::SubmitMultisig.value(), res);
|
||||
match res {
|
||||
Ok(res) => res,
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
Err(_) => Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs the xmr rpc 'exchange_multisig_keys' method
|
||||
pub async fn exchange_multisig_keys(
|
||||
force_update_use_with_caution: bool,
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use crate::{
|
||||
db,
|
||||
models::*,
|
||||
|
@ -10,8 +5,21 @@ use crate::{
|
|||
reqres,
|
||||
utils,
|
||||
};
|
||||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
|
||||
/*
|
||||
TODOs(c2m):
|
||||
- API to valid payment and import multisig info
|
||||
- update order status
|
||||
*/
|
||||
|
||||
|
||||
enum StatusType {
|
||||
_Delivered,
|
||||
MultisigMissing,
|
||||
|
@ -35,8 +43,7 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
|
|||
info!("creating order");
|
||||
let wallet_name = String::from(crate::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(crate::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
let ts = chrono::offset::Utc::now().timestamp();
|
||||
let orid: String = format!("O{}", utils::generate_rnd());
|
||||
|
@ -144,3 +151,18 @@ pub fn modify(o: Json<Order>) -> Order {
|
|||
db::Interface::write(&s.env, &s.handle, &u_order.pid, &Order::to_db(&u_order));
|
||||
return u_order;
|
||||
}
|
||||
|
||||
/// Sign and submit multisig
|
||||
pub async fn sign_and_submit_multisig(
|
||||
orid: &String,
|
||||
tx_data_hex: &String) -> reqres::XmrRpcSubmitMultisigResponse {
|
||||
info!("signin and submitting multisig");
|
||||
let r_sign: reqres::XmrRpcSignMultisigResponse =
|
||||
monero::sign_multisig(String::from(tx_data_hex)).await;
|
||||
let r_submit: reqres::XmrRpcSubmitMultisigResponse =
|
||||
monero::submit_multisig(r_sign.result.tx_data_hex).await;
|
||||
if r_submit.result.tx_hash_list.len() == 0 {
|
||||
error!("unable to submit payment for order: {}", orid);
|
||||
}
|
||||
r_submit
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// Product repo/service layer
|
||||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use crate::{
|
||||
db,
|
||||
models::*,
|
||||
utils,
|
||||
};
|
||||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
};
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
/// Create a new product
|
||||
|
@ -16,7 +16,7 @@ pub fn create(d: Json<Product>) -> Product {
|
|||
let pid: String = format!("product{}", utils::generate_rnd());
|
||||
if !validate_product(&d) {
|
||||
error!("invalid product");
|
||||
return Default::default()
|
||||
return Default::default();
|
||||
}
|
||||
let new_product = Product {
|
||||
pid: String::from(&pid),
|
||||
|
|
|
@ -343,6 +343,12 @@ pub struct XmrRpcImportResult {
|
|||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct XmrRpcSignMultisigResult {
|
||||
pub tx_data_hex: String,
|
||||
pub tx_hash_list: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct XmrRpcSubmitMultisigResult {
|
||||
pub tx_hash_list: Vec<String>,
|
||||
}
|
||||
|
||||
|
@ -862,6 +868,22 @@ impl Default for XmrRpcSignMultisigResponse {
|
|||
fn default() -> Self {
|
||||
XmrRpcSignMultisigResponse {
|
||||
result: XmrRpcSignMultisigResult {
|
||||
tx_data_hex: utils::empty_string(),
|
||||
tx_hash_list: Vec::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct XmrRpcSubmitMultisigResponse {
|
||||
pub result: XmrRpcSubmitMultisigResult,
|
||||
}
|
||||
|
||||
impl Default for XmrRpcSubmitMultisigResponse {
|
||||
fn default() -> Self {
|
||||
XmrRpcSubmitMultisigResponse {
|
||||
result: XmrRpcSubmitMultisigResult {
|
||||
tx_hash_list: Vec::new(),
|
||||
},
|
||||
}
|
||||
|
@ -1123,3 +1145,20 @@ impl Default for MultisigInfoRequest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Request for signing and submitting the unsigned txset
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct SignAndSubmitRequest {
|
||||
pub orid: String,
|
||||
pub txset: String,
|
||||
}
|
||||
|
||||
impl Default for SignAndSubmitRequest {
|
||||
fn default() -> Self {
|
||||
SignAndSubmitRequest {
|
||||
orid: utils::empty_string(),
|
||||
txset: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,9 +237,11 @@ pub fn empty_string() -> String {
|
|||
pub const fn string_limit() -> usize {
|
||||
512
|
||||
}
|
||||
|
||||
pub const fn gpg_key_limit() -> usize {
|
||||
4096
|
||||
}
|
||||
|
||||
pub const fn message_limit() -> usize {
|
||||
9999
|
||||
}
|
||||
|
@ -644,8 +646,7 @@ pub async fn estimate_fee() -> u128 {
|
|||
pub async fn can_transfer(invoice: u128) -> bool {
|
||||
let wallet_name = String::from(crate::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(crate::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let balance = monero::get_balance().await;
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
|
|
|
@ -692,8 +692,7 @@ fn send_payment_req(
|
|||
log::debug!("sending {} piconero(s) to: {}", &d.amount, &d.address);
|
||||
let wallet_name = String::from(neveko_core::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let transfer: reqres::XmrRpcTransferResponse = monero::transfer(d).await;
|
||||
// in order to keep the jwp creation process transparent to the user
|
||||
|
|
|
@ -366,8 +366,7 @@ fn send_address_req(tx: Sender<reqres::XmrRpcAddressResponse>, ctx: egui::Contex
|
|||
tokio::spawn(async move {
|
||||
let wallet_name = String::from(neveko_core::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let address: reqres::XmrRpcAddressResponse = monero::get_address().await;
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
|
@ -380,8 +379,7 @@ fn send_balance_req(tx: Sender<reqres::XmrRpcBalanceResponse>, ctx: egui::Contex
|
|||
tokio::spawn(async move {
|
||||
let wallet_name = String::from(neveko_core::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let balance: reqres::XmrRpcBalanceResponse = monero::get_balance().await;
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
|
|
|
@ -141,8 +141,7 @@ fn send_address_req(tx: Sender<reqres::XmrRpcAddressResponse>, ctx: egui::Contex
|
|||
tokio::spawn(async move {
|
||||
let wallet_name = String::from(neveko_core::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let address: reqres::XmrRpcAddressResponse = monero::get_address().await;
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
|
@ -159,8 +158,7 @@ fn send_sweep_all_req(
|
|||
tokio::spawn(async move {
|
||||
let wallet_name = String::from(neveko_core::APP_NAME);
|
||||
let wallet_password =
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
|
||||
.unwrap_or(String::from("password"));
|
||||
std::env::var(neveko_core::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let result: reqres::XmrRpcSweepAllResponse = monero::sweep_all(address).await;
|
||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
|
|
|
@ -79,10 +79,24 @@ pub async fn create_dispute(
|
|||
Custom(Status::Ok, Json(m_dispute))
|
||||
}
|
||||
|
||||
/// Create a dispute
|
||||
/// Fetch a dispute
|
||||
#[get("/<did>")]
|
||||
pub async fn get_dispute(_token: auth::BearerToken, did: String) -> Custom<Json<models::Dispute>> {
|
||||
let m_dispute: models::Dispute = dispute::find(&did);
|
||||
Custom(Status::Ok, Json(m_dispute))
|
||||
}
|
||||
|
||||
/// Create a dispute
|
||||
#[post("/sign/submit", data = "<r_data>")]
|
||||
pub async fn sign_and_submit_multisig(
|
||||
r_data: Json<reqres::SignAndSubmitRequest>,
|
||||
_token: auth::BearerToken,
|
||||
) -> Custom<Json<reqres::SignAndSubmitRequest>> {
|
||||
let result: reqres::XmrRpcSubmitMultisigResponse =
|
||||
order::sign_and_submit_multisig(&r_data.orid, &r_data.txset).await;
|
||||
if result.result.tx_hash_list.is_empty() {
|
||||
return Custom(Status::BadRequest, Json(Default::default()));
|
||||
}
|
||||
Custom(Status::Ok, Json(Default::default()))
|
||||
}
|
||||
// END JSON APIs
|
||||
|
|
|
@ -21,7 +21,10 @@ async fn rocket() -> _ {
|
|||
)
|
||||
.mount(
|
||||
"/order",
|
||||
routes![controller::get_order, controller::update_order],
|
||||
routes![
|
||||
controller::get_order,
|
||||
controller::sign_and_submit_multisig,
|
||||
controller::update_order],
|
||||
)
|
||||
.mount("/orders", routes![controller::get_orders])
|
||||
.mount("/products", routes![controller::get_products])
|
||||
|
|
Loading…
Reference in a new issue