Add API method for generating invoices

This commit is contained in:
silverpill 2022-08-17 15:36:27 +00:00
parent 084e0064be
commit cd09fe0801
5 changed files with 131 additions and 4 deletions

View file

@ -684,6 +684,34 @@ paths:
description: User's wallet address is not known or not verified
418:
description: Blockchain integration is not enabled
/api/v1/subscriptions/invoices:
post:
summary: Create invoice
requestBody:
content:
application/json:
schema:
type: object
properties:
sender:
description: Sender actor address (webfinger account URI).
type: string
example: user@example.org
recipient:
description: Recipient ID.
type: string
format: uuid
responses:
200:
description: Invoice created.
content:
application/json:
schema:
$ref: '#/components/schemas/Invoice'
404:
description: Sender or recipient not found.
418:
description: Blockchain integration is not enabled.
/api/v1/timelines/public:
get:
summary: View local public posts.
@ -924,6 +952,24 @@ components:
description: IPFS gateway URL.
type: string
nullable: true
Invoice:
type: object
properties:
id:
description: Invoice ID.
type: string
format: uuid
sender_id:
description: The profile ID of the sender.
type: string
format: uuid
recipient_id:
description: The profile ID of the recipient.
type: string
format: uuid
payment_address:
description: Payment address.
type: string
Mention:
type: object
properties:

View file

@ -1,4 +1,32 @@
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::models::invoices::types::DbInvoice;
#[derive(Deserialize)]
pub struct InvoiceData {
pub sender: String, // acct
pub recipient: Uuid,
}
#[derive(Serialize)]
pub struct Invoice {
pub id: Uuid,
pub sender_id: Uuid,
pub recipient_id: Uuid,
pub payment_address: String,
}
impl From<DbInvoice> for Invoice {
fn from(value: DbInvoice) -> Self {
Self {
id: value.id,
sender_id: value.sender_id,
recipient_id: value.recipient_id,
payment_address: value.payment_address,
}
}
}
#[derive(Deserialize)]
pub struct SubscriptionQueryParams {

View file

@ -1,4 +1,4 @@
use actix_web::{web, HttpResponse, Scope};
use actix_web::{post, web, HttpResponse, Scope};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::activitypub::builders::update_person::prepare_update_person;
@ -12,15 +12,23 @@ use crate::ethereum::subscriptions::{
};
use crate::mastodon_api::accounts::types::Account;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::models::profiles::queries::update_profile;
use crate::models::invoices::queries::create_invoice;
use crate::models::profiles::queries::{
get_profile_by_acct,
update_profile,
};
use crate::models::profiles::types::{
MoneroSubscription,
PaymentOption,
PaymentType,
ProfileUpdateData,
};
use crate::models::users::queries::get_user_by_id;
use crate::monero::wallet::create_monero_address;
use crate::utils::currencies::Currency;
use super::types::{
Invoice,
InvoiceData,
SubscriptionQueryParams,
SubscriptionSettings,
};
@ -123,8 +131,36 @@ pub async fn subscriptions_enabled(
Ok(HttpResponse::Ok().json(account))
}
#[post("/invoices")]
async fn create_invoice_view(
config: web::Data<Config>,
db_pool: web::Data<Pool>,
invoice_data: web::Json<InvoiceData>,
) -> Result<HttpResponse, HttpError> {
let monero_config = config.blockchain()
.ok_or(HttpError::NotSupported)?
.monero_config()
.ok_or(HttpError::NotSupported)?;
let db_client = &**get_database_client(&db_pool).await?;
let sender = get_profile_by_acct(db_client, &invoice_data.sender).await?;
let recipient = get_user_by_id(db_client, &invoice_data.recipient).await?;
let payment_address = create_monero_address(monero_config).await
.map_err(|_| HttpError::InternalError)?
.to_string();
let db_invoice = create_invoice(
db_client,
&sender.id,
&recipient.id,
&monero_config.chain_id,
&payment_address,
).await?;
let invoice = Invoice::from(db_invoice);
Ok(HttpResponse::Ok().json(invoice))
}
pub fn subscription_api_scope() -> Scope {
web::scope("/api/v1/subscriptions")
.route("/authorize", web::get().to(authorize_subscription))
.route("/enable", web::post().to(subscriptions_enabled))
.service(create_invoice_view)
}

View file

@ -1,2 +1,2 @@
pub mod queries;
mod types;
pub mod types;

View file

@ -1,7 +1,10 @@
use monero_rpc::RpcClient;
use monero_rpc::monero::Address;
use crate::config::MoneroConfig;
const DEFAULT_ACCOUNT: u32 = 0;
#[derive(thiserror::Error, Debug)]
pub enum MoneroError {
#[error(transparent)]
@ -19,3 +22,17 @@ pub async fn create_monero_wallet(
wallet_client.create_wallet(name, password, language).await?;
Ok(())
}
pub async fn create_monero_address(
config: &MoneroConfig,
) -> Result<Address, MoneroError> {
let wallet_client = RpcClient::new(config.wallet_url.clone()).wallet();
wallet_client.open_wallet(
config.wallet_name.clone(),
config.wallet_password.clone(),
).await?;
let (address, address_index) =
wallet_client.create_address(DEFAULT_ACCOUNT, None).await?;
log::info!("created monero address {}/{}", DEFAULT_ACCOUNT, address_index);
Ok(address)
}