Skip to main content

hypercall_db_diesel/
rsm_credit.rs

1//! RSM credit and cash-ledger persistence trait implementations.
2
3use anyhow::Result;
4use async_trait::async_trait;
5use hypercall_types::WalletAddress;
6
7use crate::DatabaseHandler;
8
9#[async_trait]
10impl hypercall_db::RsmCreditReader for DatabaseHandler {
11    fn directive_outbox_exists_sync(&self, directive_id: &str) -> Result<bool> {
12        DatabaseHandler::directive_outbox_exists_sync(self, directive_id)
13    }
14
15    async fn get_max_rsm_deposit_credit_observed_block(&self) -> Result<Option<u64>> {
16        DatabaseHandler::get_max_rsm_deposit_credit_observed_block(self).await
17    }
18
19    fn get_exchange_cash_ledger_watermark_sync(&self) -> Result<Option<i64>> {
20        DatabaseHandler::get_exchange_cash_ledger_watermark_sync(self)
21    }
22
23    async fn get_option_instrument_for_credit(
24        &self,
25        token: &WalletAddress,
26    ) -> Result<Option<hypercall_db::OptionInstrumentForCredit>> {
27        DatabaseHandler::get_option_instrument_for_credit(self, token).await
28    }
29
30    async fn list_recent_cash_deposit_monitoring_rows(
31        &self,
32        limit: i64,
33        offset: i64,
34    ) -> Result<Vec<hypercall_db::DepositMonitoringRow>> {
35        DatabaseHandler::list_recent_cash_deposit_monitoring_rows(self, limit, offset).await
36    }
37}
38
39#[async_trait]
40impl hypercall_db::RsmCreditWriter for DatabaseHandler {
41    async fn ensure_observed_deposit_account(&self, account: &WalletAddress) -> Result<()> {
42        DatabaseHandler::ensure_observed_deposit_account(self, account).await
43    }
44
45    async fn claim_rsm_deposit_credit(
46        &self,
47        input: &hypercall_db::RsmDepositCreditClaimInput,
48    ) -> Result<hypercall_db::RsmDepositCreditClaimRecord> {
49        DatabaseHandler::claim_rsm_deposit_credit(self, input).await
50    }
51
52    async fn mark_rsm_deposit_credit_submitted(&self, request_id: &str) -> Result<()> {
53        DatabaseHandler::mark_rsm_deposit_credit_submitted(self, request_id).await
54    }
55
56    async fn mark_rsm_deposit_credit_failed(&self, request_id: &str, error: &str) -> Result<()> {
57        DatabaseHandler::mark_rsm_deposit_credit_failed(self, request_id, error).await
58    }
59
60    async fn pending_rsm_usdc_deposit_for_amount(
61        &self,
62        amount_wei: &str,
63    ) -> Result<Option<hypercall_db::RsmUsdcDepositMatch>> {
64        DatabaseHandler::pending_rsm_usdc_deposit_for_amount(self, amount_wei).await
65    }
66
67    async fn pending_rsm_usdc_deposit_for_evm_tx_hash(
68        &self,
69        evm_tx_hash: &str,
70        amount_wei: &str,
71    ) -> Result<Option<hypercall_db::RsmUsdcDepositMatch>> {
72        DatabaseHandler::pending_rsm_usdc_deposit_for_evm_tx_hash(self, evm_tx_hash, amount_wei)
73            .await
74    }
75
76    async fn pending_rsm_usdc_deposit_for_credited_hypercore_event(
77        &self,
78        event_hash: &str,
79        amount_wei: &str,
80    ) -> Result<Option<hypercall_db::RsmUsdcDepositMatch>> {
81        DatabaseHandler::pending_rsm_usdc_deposit_for_credited_hypercore_event(
82            self, event_hash, amount_wei,
83        )
84        .await
85    }
86
87    async fn credited_wallet_for_hypercore_cash_event(
88        &self,
89        event_hash: &str,
90    ) -> Result<Option<WalletAddress>> {
91        DatabaseHandler::credited_wallet_for_hypercore_cash_event(self, event_hash).await
92    }
93
94    async fn non_crediting_hypercore_cash_event(
95        &self,
96        event_hash: &str,
97        amount_usdc: rust_decimal::Decimal,
98    ) -> Result<bool> {
99        DatabaseHandler::non_crediting_hypercore_cash_event(self, event_hash, amount_usdc).await
100    }
101
102    async fn apply_hypercore_cash_deposit(
103        &self,
104        input: &hypercall_db::HypercoreCashLedgerApply,
105    ) -> Result<hypercall_db::HypercoreCashLedgerApplyResult> {
106        DatabaseHandler::apply_hypercore_cash_deposit(self, input).await
107    }
108
109    async fn record_hypercore_cash_deposit_pending_margin_mode(
110        &self,
111        input: &hypercall_db::HypercoreCashLedgerApply,
112    ) -> Result<()> {
113        DatabaseHandler::record_hypercore_cash_deposit_pending_margin_mode(self, input).await
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use diesel::sql_types::{BigInt, Binary, Text};
120    use diesel::RunQueryDsl;
121    use hypercall_db::RsmCreditReader;
122    use hypercall_types::WalletAddress;
123
124    use crate::test_helpers::TestDb;
125
126    fn wallet(byte: u8) -> WalletAddress {
127        WalletAddress::from([byte; 20])
128    }
129
130    #[tokio::test]
131    async fn rsm_credit_reader_lists_recent_cash_deposit_monitoring_rows() {
132        let db = TestDb::new().await.expect("test db");
133        let account = wallet(7);
134        let token = wallet(9);
135
136        {
137            let mut conn = db.handler.pool().get().expect("db connection");
138            diesel::sql_query(
139                "INSERT INTO rsm_deposit_credits
140                 (tx_hash, log_index, observed_block, account, token, amount_wei, credit_kind,
141                  request_id, status, created_at, updated_at)
142                 VALUES ($1, $2, $3, $4, $5, $6, 'usdc', $7, 'submitted', now(), now())",
143            )
144            .bind::<Text, _>("0xmonitoringusdc")
145            .bind::<BigInt, _>(3_i64)
146            .bind::<BigInt, _>(42_i64)
147            .bind::<Binary, _>(account.as_bytes())
148            .bind::<Binary, _>(token.as_bytes())
149            .bind::<Text, _>("123450000")
150            .bind::<Text, _>("rsm-monitoring-usdc")
151            .execute(&mut conn)
152            .expect("insert rsm deposit credit");
153        }
154
155        let reader: &dyn RsmCreditReader = db.handler.as_ref();
156        let rows = reader
157            .list_recent_cash_deposit_monitoring_rows(10, 0)
158            .await
159            .expect("monitoring rows");
160
161        assert_eq!(rows.len(), 1);
162        let row = &rows[0];
163        assert_eq!(row.source, "exchange_usdc");
164        assert_eq!(row.status, "submitted");
165        assert_eq!(row.correlation_status, "writer_action_correlated");
166        assert_eq!(row.wallet, account);
167        assert_eq!(row.amount_usdc, "123.4500000000000000");
168        assert_eq!(row.event_hash, "0xmonitoringusdc");
169        assert_eq!(row.tx_hash.as_deref(), Some("0xmonitoringusdc"));
170        assert_eq!(row.request_id.as_deref(), Some("rsm-monitoring-usdc"));
171        assert_eq!(row.observed_block, Some(42));
172        assert_eq!(row.log_index, Some(3));
173        assert_eq!(row.ledger_event_id, None);
174    }
175}