use serde::Deserialize;
use crate::account::{ActionKind, Signers};
use crate::utils::Dec;
use crate::utils::sign::{L1Action, Map, Value};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Operation {
Supply,
Withdraw,
Borrow,
Repay,
}
impl Operation {
pub const ALL: [Operation; 4] = [Operation::Supply, Operation::Withdraw, Operation::Borrow, Operation::Repay];
#[must_use]
pub const fn wire(self) -> &'static str {
match self {
Operation::Supply => "supply",
Operation::Withdraw => "withdraw",
Operation::Borrow => "borrow",
Operation::Repay => "repay",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum BadLend {
#[error("{0} is not an amount above zero")]
NotPositive(Dec),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BorrowLend {
operation: Operation,
token: u32,
amount: Option<Dec>,
}
impl BorrowLend {
pub const KEY: Signers = ActionKind::BorrowLend.signers();
pub fn new(operation: Operation, token: u32, amount: Dec) -> Result<BorrowLend, BadLend> {
match amount.is_positive() {
true => Ok(BorrowLend { operation, token, amount: Some(amount) }),
false => Err(BadLend::NotPositive(amount)),
}
}
pub fn supply(token: u32, amount: Dec) -> Result<BorrowLend, BadLend> {
BorrowLend::new(Operation::Supply, token, amount)
}
pub fn withdraw(token: u32, amount: Dec) -> Result<BorrowLend, BadLend> {
BorrowLend::new(Operation::Withdraw, token, amount)
}
pub fn borrow(token: u32, amount: Dec) -> Result<BorrowLend, BadLend> {
BorrowLend::new(Operation::Borrow, token, amount)
}
pub fn repay(token: u32, amount: Dec) -> Result<BorrowLend, BadLend> {
BorrowLend::new(Operation::Repay, token, amount)
}
#[must_use]
pub const fn withdraw_all(token: u32) -> BorrowLend {
BorrowLend { operation: Operation::Withdraw, token, amount: None }
}
#[must_use]
pub const fn repay_all(token: u32) -> BorrowLend {
BorrowLend { operation: Operation::Repay, token, amount: None }
}
#[must_use]
pub const fn operation(&self) -> Operation {
self.operation
}
#[must_use]
pub const fn token(&self) -> u32 {
self.token
}
#[must_use]
pub const fn amount(&self) -> Option<Dec> {
self.amount
}
}
impl L1Action for BorrowLend {
fn action(&self) -> Map {
let amount = match self.amount {
Some(amount) => Value::from(amount.to_wire()),
None => Value::Nil,
};
Map::new()
.put("type", "borrowLend")
.put("operation", self.operation.wire())
.put("token", self.token)
.put("amount", amount)
}
}