From f59ab51ba573d112235cd14cf530cdae74bb0c19 Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:40 -0600 Subject: [PATCH 1/6] Add typed Stellar amount helpers --- quantara/web_app/contract_tools/amounts.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 quantara/web_app/contract_tools/amounts.py diff --git a/quantara/web_app/contract_tools/amounts.py b/quantara/web_app/contract_tools/amounts.py new file mode 100644 index 00000000..3fac5144 --- /dev/null +++ b/quantara/web_app/contract_tools/amounts.py @@ -0,0 +1,20 @@ +""" +Typed helpers for converting Stellar decimal amounts to raw token units. +""" + +from decimal import Decimal, ROUND_HALF_UP + + +def from_stellar_units(amount: Decimal | str, decimals: int) -> int: + """ + Convert a human Stellar amount into raw integer token units. + """ + decimal_amount = amount if isinstance(amount, Decimal) else Decimal(amount) + return int(decimal_amount.scaleb(decimals).quantize(Decimal("1"), ROUND_HALF_UP)) + + +def to_stellar_units(raw_amount: int, decimals: int) -> Decimal: + """ + Convert raw integer token units into a human Stellar decimal amount. + """ + return Decimal(raw_amount).scaleb(-decimals) From 950143780c642c19bbfe3d8ce8a4d76a3afc2542 Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:41 -0600 Subject: [PATCH 2/6] Add typed Stellar amount helpers --- quantara/web_app/contract_tools/mixins/deposit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantara/web_app/contract_tools/mixins/deposit.py b/quantara/web_app/contract_tools/mixins/deposit.py index 499e842b..ff0c76e0 100644 --- a/quantara/web_app/contract_tools/mixins/deposit.py +++ b/quantara/web_app/contract_tools/mixins/deposit.py @@ -7,6 +7,7 @@ from decimal import Decimal +from web_app.contract_tools.amounts import from_stellar_units from web_app.contract_tools.constants import TokenParams from web_app.contract_tools.blockchain_call import StellarClient @@ -38,7 +39,7 @@ async def get_transaction_data( """ deposit_token_address = TokenParams.get_token_address(deposit_token) decimal = TokenParams.get_token_decimals(deposit_token_address) - amount = int(Decimal(amount) * 10 ** decimal) + amount = from_stellar_units(amount, decimal) loop_liquidity_data = await client.get_loop_liquidity_data( deposit_token_address, From d6674deefeb3f418c499ff13bcfd35c013857bdb Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:41 -0600 Subject: [PATCH 3/6] Add typed Stellar amount helpers --- quantara/web_app/contract_tools/mixins/health_ratio.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/quantara/web_app/contract_tools/mixins/health_ratio.py b/quantara/web_app/contract_tools/mixins/health_ratio.py index 6b216bbf..3a41a824 100644 --- a/quantara/web_app/contract_tools/mixins/health_ratio.py +++ b/quantara/web_app/contract_tools/mixins/health_ratio.py @@ -9,6 +9,7 @@ import asyncio from decimal import Decimal +from web_app.contract_tools.amounts import to_stellar_units from web_app.contract_tools.blockchain_call import StellarClient from web_app.contract_tools.constants import TokenParams @@ -86,7 +87,11 @@ async def get_health_ratio_and_tvl(cls, account_address: str, client: StellarCli ) borrowed_price = prices.get(borrowed_token, Decimal("0")) - debt_usdc = debt_raw * borrowed_price / Decimal(10 ** int(TokenParams.get_token_decimals(borrowed_token))) + debt_amount = to_stellar_units( + debt_raw, + int(TokenParams.get_token_decimals(borrowed_token)), + ) + debt_usdc = debt_amount * borrowed_price if debt_usdc == 0: return "-1", "0" From 1dd846bf7d2fb91d9c8b96698b31bf23ff0768d3 Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:42 -0600 Subject: [PATCH 4/6] Add typed Stellar amount helpers --- quantara/web_app/api/position.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/quantara/web_app/api/position.py b/quantara/web_app/api/position.py index cd083a09..8c37e3c2 100644 --- a/quantara/web_app/api/position.py +++ b/quantara/web_app/api/position.py @@ -2,7 +2,7 @@ This module handles position-related API endpoints for the Stellar-based Quantara protocol. """ -from decimal import Decimal, InvalidOperation +from decimal import InvalidOperation from uuid import UUID from fastapi import APIRouter, HTTPException, Query, Depends, Request @@ -22,6 +22,7 @@ from web_app.api.wallet_auth import verify_wallet_signature from web_app.contract_tools.constants import TokenMultipliers, TokenParams from web_app.contract_tools.mixins import DashboardMixin, DepositMixin, PositionMixin +from web_app.contract_tools.amounts import from_stellar_units from web_app.db.crud import PositionDBConnector, TransactionDBConnector from web_app.api.dependencies import get_stellar_client from web_app.contract_tools.blockchain_call import StellarClient @@ -302,8 +303,9 @@ async def get_add_deposit_data(request: Request, position_id: UUID, amount: str, try: token_address = TokenParams.get_token_address(token_symbol) - token_amount = int( - Decimal(amount) * 10 ** TokenParams.get_token_decimals(token_address) + token_amount = from_stellar_units( + amount, + TokenParams.get_token_decimals(token_address), ) except InvalidOperation: raise HTTPException(status_code=400, detail="Amount is not a number") From 3ecbfc5ff1410a598bfcdc7c2a49a41efeb008b9 Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:43 -0600 Subject: [PATCH 5/6] Add typed Stellar amount helpers --- quantara/web_app/tests/test_amount_helpers.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 quantara/web_app/tests/test_amount_helpers.py diff --git a/quantara/web_app/tests/test_amount_helpers.py b/quantara/web_app/tests/test_amount_helpers.py new file mode 100644 index 00000000..ec6562b9 --- /dev/null +++ b/quantara/web_app/tests/test_amount_helpers.py @@ -0,0 +1,22 @@ +from decimal import Decimal +import unittest + +from web_app.contract_tools.amounts import from_stellar_units, to_stellar_units + + +class AmountHelperTests(unittest.TestCase): + def test_from_stellar_units_scales_decimal_amounts_to_raw_units(self): + self.assertEqual(from_stellar_units(Decimal("1.5"), 7), 15_000_000) + self.assertEqual(from_stellar_units("0.01", 2), 1) + + def test_from_stellar_units_uses_round_half_up_boundary_policy(self): + self.assertEqual(from_stellar_units("1.23456784", 7), 12_345_678) + self.assertEqual(from_stellar_units("1.23456785", 7), 12_345_679) + + def test_to_stellar_units_restores_raw_amounts(self): + self.assertEqual(to_stellar_units(15_000_000, 7), Decimal("1.5000000")) + self.assertEqual(to_stellar_units(1, 2), Decimal("0.01")) + + +if __name__ == "__main__": + unittest.main() From 00cedeb5043b5e5f5cdb64c1339de688d295a8b9 Mon Sep 17 00:00:00 2001 From: silentgeckoaudit3801 Date: Fri, 24 Jul 2026 23:34:44 -0600 Subject: [PATCH 6/6] Add typed Stellar amount helpers --- .../tests/test_amount_helper_wiring_static.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 quantara/web_app/tests/test_amount_helper_wiring_static.py diff --git a/quantara/web_app/tests/test_amount_helper_wiring_static.py b/quantara/web_app/tests/test_amount_helper_wiring_static.py new file mode 100644 index 00000000..42cfb4ee --- /dev/null +++ b/quantara/web_app/tests/test_amount_helper_wiring_static.py @@ -0,0 +1,24 @@ +from pathlib import Path +import unittest + + +WEB_APP_ROOT = Path(__file__).resolve().parents[1] + + +class AmountHelperWiringStaticTests(unittest.TestCase): + def test_distributed_raw_unit_conversions_use_amount_helper(self): + source_roots = [ + WEB_APP_ROOT / "api" / "position.py", + WEB_APP_ROOT / "contract_tools" / "mixins" / "deposit.py", + WEB_APP_ROOT / "contract_tools" / "mixins" / "health_ratio.py", + ] + joined_source = "\n".join(path.read_text() for path in source_roots) + + self.assertIn("from_stellar_units(", joined_source) + self.assertIn("to_stellar_units(", joined_source) + self.assertNotIn("int(Decimal(amount) * 10 **", joined_source) + self.assertNotIn("Decimal(10 ** int(TokenParams.get_token_decimals", joined_source) + + +if __name__ == "__main__": + unittest.main()