Store requested payment amount for each invoice

This commit is contained in:
silverpill 2022-09-18 00:23:20 +00:00
parent bc0de60b5c
commit a1ab21a702
7 changed files with 27 additions and 2 deletions

View file

@ -761,6 +761,10 @@ paths:
description: Recipient ID. description: Recipient ID.
type: string type: string
format: uuid format: uuid
amount:
description: Requested payment amount (in atomic units).
type: integer
example: 100000000
responses: responses:
200: 200:
description: Invoice created. description: Invoice created.
@ -1082,6 +1086,10 @@ components:
payment_address: payment_address:
description: Payment address. description: Payment address.
type: string type: string
amount:
description: Requested payment amount (in atomic units).
type: integer
example: 100000000
status: status:
description: Invoice status. description: Invoice status.
type: string type: string

View file

@ -0,0 +1,2 @@
ALTER TABLE invoice ADD COLUMN amount BIGINT NOT NULL DEFAULT 0 CHECK (amount >= 0);
ALTER TABLE invoice ALTER COLUMN amount DROP DEFAULT;

View file

@ -143,6 +143,7 @@ CREATE TABLE invoice (
recipient_id UUID NOT NULL REFERENCES user_account (id) ON DELETE CASCADE, recipient_id UUID NOT NULL REFERENCES user_account (id) ON DELETE CASCADE,
chain_id VARCHAR(50) NOT NULL, chain_id VARCHAR(50) NOT NULL,
payment_address VARCHAR(200) NOT NULL, payment_address VARCHAR(200) NOT NULL,
amount BIGINT NOT NULL CHECK (amount >= 0),
invoice_status SMALLINT NOT NULL DEFAULT 1, invoice_status SMALLINT NOT NULL DEFAULT 1,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (chain_id, payment_address) UNIQUE (chain_id, payment_address)

View file

@ -9,6 +9,7 @@ use crate::models::profiles::types::PaymentOption;
pub struct InvoiceData { pub struct InvoiceData {
pub sender_id: Uuid, pub sender_id: Uuid,
pub recipient_id: Uuid, pub recipient_id: Uuid,
pub amount: i64,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -17,6 +18,7 @@ pub struct Invoice {
pub sender_id: Uuid, pub sender_id: Uuid,
pub recipient_id: Uuid, pub recipient_id: Uuid,
pub payment_address: String, pub payment_address: String,
pub amount: i64,
pub status: String, pub status: String,
} }
@ -33,6 +35,7 @@ impl From<DbInvoice> for Invoice {
sender_id: value.sender_id, sender_id: value.sender_id,
recipient_id: value.recipient_id, recipient_id: value.recipient_id,
payment_address: value.payment_address, payment_address: value.payment_address,
amount: value.amount,
status: status.to_string(), status: status.to_string(),
} }
} }

View file

@ -178,6 +178,9 @@ async fn create_invoice_view(
if invoice_data.sender_id == invoice_data.recipient_id { if invoice_data.sender_id == invoice_data.recipient_id {
return Err(ValidationError("sender must be different from recipient").into()); return Err(ValidationError("sender must be different from recipient").into());
}; };
if invoice_data.amount <= 0 {
return Err(ValidationError("amount must be positive").into());
};
let db_client = &**get_database_client(&db_pool).await?; let db_client = &**get_database_client(&db_pool).await?;
let sender = get_profile_by_id(db_client, &invoice_data.sender_id).await?; let sender = get_profile_by_id(db_client, &invoice_data.sender_id).await?;
let recipient = get_user_by_id(db_client, &invoice_data.recipient_id).await?; let recipient = get_user_by_id(db_client, &invoice_data.recipient_id).await?;
@ -190,6 +193,7 @@ async fn create_invoice_view(
&recipient.id, &recipient.id,
&monero_config.chain_id, &monero_config.chain_id,
&payment_address, &payment_address,
invoice_data.amount,
).await?; ).await?;
let invoice = Invoice::from(db_invoice); let invoice = Invoice::from(db_invoice);
Ok(HttpResponse::Ok().json(invoice)) Ok(HttpResponse::Ok().json(invoice))

View file

@ -13,6 +13,7 @@ pub async fn create_invoice(
recipient_id: &Uuid, recipient_id: &Uuid,
chain_id: &ChainId, chain_id: &ChainId,
payment_address: &str, payment_address: &str,
amount: i64,
) -> Result<DbInvoice, DatabaseError> { ) -> Result<DbInvoice, DatabaseError> {
let invoice_id = new_uuid(); let invoice_id = new_uuid();
let row = db_client.query_one( let row = db_client.query_one(
@ -22,9 +23,10 @@ pub async fn create_invoice(
sender_id, sender_id,
recipient_id, recipient_id,
chain_id, chain_id,
payment_address payment_address,
amount
) )
VALUES ($1, $2, $3, $4, $5) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING invoice RETURNING invoice
", ",
&[ &[
@ -33,6 +35,7 @@ pub async fn create_invoice(
&recipient_id, &recipient_id,
&chain_id, &chain_id,
&payment_address, &payment_address,
&amount,
], ],
).await.map_err(catch_unique_violation("invoice"))?; ).await.map_err(catch_unique_violation("invoice"))?;
let invoice = row.try_get("invoice")?; let invoice = row.try_get("invoice")?;
@ -139,17 +142,20 @@ mod tests {
reference: "mainnet".to_string(), reference: "mainnet".to_string(),
}; };
let payment_address = "8MxABajuo71BZya9"; let payment_address = "8MxABajuo71BZya9";
let amount = 100000000000109212;
let invoice = create_invoice( let invoice = create_invoice(
db_client, db_client,
&sender.id, &sender.id,
&recipient.id, &recipient.id,
&chain_id, &chain_id,
payment_address, payment_address,
amount,
).await.unwrap(); ).await.unwrap();
assert_eq!(invoice.sender_id, sender.id); assert_eq!(invoice.sender_id, sender.id);
assert_eq!(invoice.recipient_id, recipient.id); assert_eq!(invoice.recipient_id, recipient.id);
assert_eq!(invoice.chain_id, chain_id); assert_eq!(invoice.chain_id, chain_id);
assert_eq!(invoice.payment_address, payment_address); assert_eq!(invoice.payment_address, payment_address);
assert_eq!(invoice.amount, amount);
assert!(matches!(invoice.invoice_status, InvoiceStatus::Open)); assert!(matches!(invoice.invoice_status, InvoiceStatus::Open));
} }
} }

View file

@ -53,6 +53,7 @@ pub struct DbInvoice {
pub recipient_id: Uuid, pub recipient_id: Uuid,
pub chain_id: ChainId, pub chain_id: ChainId,
pub payment_address: String, pub payment_address: String,
pub amount: i64, // requested payment amount
pub invoice_status: InvoiceStatus, pub invoice_status: InvoiceStatus,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }