From b72e56a54f868d9d64452625de35fe554495b19b Mon Sep 17 00:00:00 2001 From: Andrii Bogomolov Date: Thu, 17 Oct 2024 13:10:11 +0200 Subject: [PATCH 01/25] dashboard-API-fixing Dashboard-API-fixing --- .../src/pages/spotnet/dashboard/Dashboard.jsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx index a62213db..214a2ce6 100644 --- a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx +++ b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx @@ -10,7 +10,7 @@ import axios from 'axios'; import './dashboard.css'; import {ETH_ADDRESS} from "../../../utils/constants"; -const backendUrl = process.env.REACT_APP_BACKEND_URL || 'http://0.0.0.0:8000'; +const backendUrl = process.env.REACT_APP_BACKEND_URL || 'https://spotnet.xyz'; const fetchCardData = async ({ walletId }) => { if (!walletId) { @@ -58,6 +58,7 @@ const Dashboard = ({ walletId }) => { ]; useEffect(() => { + const getData = async () => { if (!walletId) { console.error("getData: walletId is undefined"); @@ -184,17 +185,17 @@ const Dashboard = ({ walletId }) => { -
- -
))} +
+ +
); }; From 28ae2cc4a68edb8a8d6236c839fd6375fc8d5301 Mon Sep 17 00:00:00 2001 From: Andrii Bogomolov Date: Thu, 17 Oct 2024 20:49:52 +0200 Subject: [PATCH 02/25] dashboard backendUrl update dashboard backendUrl update --- frontend/src/pages/spotnet/dashboard/Dashboard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx index 214a2ce6..f20fdade 100644 --- a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx +++ b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx @@ -10,7 +10,7 @@ import axios from 'axios'; import './dashboard.css'; import {ETH_ADDRESS} from "../../../utils/constants"; -const backendUrl = process.env.REACT_APP_BACKEND_URL || 'https://spotnet.xyz'; +const backendUrl = process.env.REACT_APP_BACKEND_URL || 'http://0.0.0.0:8000'; const fetchCardData = async ({ walletId }) => { if (!walletId) { From 138ca25269f1b6bb231898743d1a555ed67cdcde Mon Sep 17 00:00:00 2001 From: Andrii Bogomolov Date: Fri, 18 Oct 2024 13:42:07 +0200 Subject: [PATCH 03/25] feat/added plug to dashboard Added plug to dashboard in case of missing API data --- .../src/pages/spotnet/dashboard/Dashboard.jsx | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx index f20fdade..79a852c3 100644 --- a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx +++ b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx @@ -50,7 +50,6 @@ const Dashboard = ({ walletId }) => { const [cardData, setCardData] = useState([]); const [healthFactor, setHealthFactor] = useState(null); const [loading, setLoading] = useState(true); - const [error, setError] = useState(false); const starData = [ { top: 1, left: 0, size: 1.5 }, { top: 75, left: 35, size: 2.5 }, @@ -62,7 +61,6 @@ const Dashboard = ({ walletId }) => { const getData = async () => { if (!walletId) { console.error("getData: walletId is undefined"); - setError(true); setLoading(false); return; } @@ -70,7 +68,8 @@ const Dashboard = ({ walletId }) => { const data = await fetchCardData({ walletId }); if (data && data.zklend_position && data.zklend_position.products) { const positions = data.zklend_position.products[0].positions || []; - const healthRatio = data.zklend_position.products[0].health_ratio || 0; + const healthRatio = data.zklend_position.products[0].health_ratio; + console.log("Positions:", positions); const cardData = positions.map((position, index) => { const isFirstCard = index === 0; @@ -81,7 +80,7 @@ const Dashboard = ({ walletId }) => { return { title: "Collateral & Earnings", icon: CollateralIcon, - balance: position.totalBalances[Object.keys(position.totalBalances)[0]] || 0, + balance: position.totalBalances[Object.keys(position.totalBalances)[0]], currencyName: isEthereum ? "Ethereum" : "STRK", currencyIcon: isEthereum ? EthIcon : StrkIcon, }; @@ -90,7 +89,7 @@ const Dashboard = ({ walletId }) => { return { title: "Borrow", icon: BorrowIcon, - balance: position.totalBalances[Object.keys(position.totalBalances)[0]] || 0, + balance: position.totalBalances[Object.keys(position.totalBalances)[0]], currencyName: "USD Coin", currencyIcon: UsdIcon, }; @@ -98,38 +97,35 @@ const Dashboard = ({ walletId }) => { setCardData(cardData); setHealthFactor(healthRatio); - setError(false); } else { console.error("Data is missing or incorrectly formatted"); - setError(true); - setCardData([]); - setHealthFactor(0); + setCardData([{ + title: "Collateral & Earnings", + icon: CollateralIcon, + balance: '0.00', + currencyName: 'Ethereum', + currencyIcon: EthIcon, + }, + { + title: "Borrow", + icon: BorrowIcon, + balance: '0.00', + currencyName: 'USD Coin', + currencyIcon: UsdIcon, + },]); + setHealthFactor('0.00'); } setLoading(false); }; - const timeoutId = setTimeout(() => { - if (loading) { - setError(true); - setLoading(false); - setCardData([]); - setHealthFactor(0); - } - }, 10000); - getData(); - return () => clearTimeout(timeoutId); }, [walletId]); if (loading) { return
Loading...
; } - if (error || !cardData.length) { - return
Error during getting the data. Please try again later.
; - } - return (
{starData.map((star, index) => ( From 25c58e42f107058b9ed8ee60233eaf78016268aa Mon Sep 17 00:00:00 2001 From: UzNaZ Date: Sun, 20 Oct 2024 19:26:34 +0200 Subject: [PATCH 04/25] added missing response models --- web_app/api/dashboard.py | 18 ++++++++++------ web_app/api/serializers/dashboard.py | 10 +++++++-- web_app/api/serializers/transaction.py | 10 +++++++++ web_app/api/user.py | 29 +++++++++++++++----------- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/web_app/api/dashboard.py b/web_app/api/dashboard.py index 04292a1f..196e7675 100644 --- a/web_app/api/dashboard.py +++ b/web_app/api/dashboard.py @@ -2,26 +2,32 @@ from fastapi import APIRouter from starlette.requests import Request - -from web_app.db.crud import PositionDBConnector +from web_app.api.serializers.dashboard import Dashboard from web_app.contract_tools.mixins.dashboard import DashboardMixin +from web_app.db.crud import PositionDBConnector router = APIRouter() position_db_connector = PositionDBConnector() -@router.get("/api/dashboard") -async def get_dashboard(request: Request, wallet_id: str) -> dict: +@router.get("/api/dashboard", response_model=Dashboard) +async def get_dashboard(request: Request, wallet_id: str) -> Dashboard: """ Get the dashboard with the balances, multipliers, start dates, and zkLend position. :param wallet_id: Wallet ID :param request: HTTP request :return: template response """ - contract_address = position_db_connector.get_contract_address_by_wallet_id(wallet_id) + contract_address = position_db_connector.get_contract_address_by_wallet_id( + wallet_id + ) opened_positions = position_db_connector.get_positions_by_wallet_id(wallet_id) - first_opened_position = opened_positions[0] if opened_positions else collections.defaultdict(lambda: None) + first_opened_position = ( + opened_positions[0] + if opened_positions + else collections.defaultdict(lambda: None) + ) # Fetch zkLend position for the wallet ID zklend_position = await DashboardMixin.get_zklend_position(contract_address) diff --git a/web_app/api/serializers/dashboard.py b/web_app/api/serializers/dashboard.py index 3fb49325..10d41d09 100644 --- a/web_app/api/serializers/dashboard.py +++ b/web_app/api/serializers/dashboard.py @@ -1,8 +1,7 @@ from decimal import Decimal from typing import Dict, List, Optional -from pydantic import BaseModel, RootModel, Field, validator - +from pydantic import BaseModel, Field, RootModel, validator from web_app.contract_tools.constants import TokenParams @@ -67,3 +66,10 @@ def convert_products(cls, products): class Config: populate_by_name = True + + +class Dashboard(BaseModel): + balances: dict[str, str] + multipliers: dict[str, list] + start_dates: dict[str, list] + zklend_position: ZkLendPositionResponse diff --git a/web_app/api/serializers/transaction.py b/web_app/api/serializers/transaction.py index 1c392260..2a450b0e 100644 --- a/web_app/api/serializers/transaction.py +++ b/web_app/api/serializers/transaction.py @@ -65,6 +65,7 @@ class RepayTransactionDataResponse(BaseModel): """ Pydantic model for the repay transaction data response. """ + supply_token: str debt_token: str pool_key: PoolKey @@ -78,5 +79,14 @@ class UpdateUserContractRequest(BaseModel): """ Pydantic model for the update user contract request. """ + wallet_id: str contract_address: str + + +class DeploymentStatus(BaseModel): + is_contract_deployed: bool + + +class ContractAddress(BaseModel): + contract_address: str | None diff --git a/web_app/api/user.py b/web_app/api/user.py index 7fbc96b0..b88edc9b 100644 --- a/web_app/api/user.py +++ b/web_app/api/user.py @@ -1,31 +1,36 @@ +from typing import Literal + from fastapi import APIRouter, Request +from web_app.api.serializers.transaction import (ContractAddress, + DeploymentStatus, + UpdateUserContractRequest) from web_app.db.crud import UserDBConnector -from web_app.api.serializers.transaction import UpdateUserContractRequest router = APIRouter() # Initialize the router user_db = UserDBConnector() -@router.get("/api/get-user-contract") -async def get_user_contract(wallet_id: str) -> int: +@router.get("/api/get-user-contract", response_model=str) +async def get_user_contract(wallet_id: str) -> str: """ Get the contract status of a user. :param wallet_id: wallet id - :return: int + :return: str """ user = user_db.get_user_by_wallet_id(wallet_id) if user is None or not user.is_contract_deployed: - return 0 + return "" else: - return user.deployed_transaction_hash + return user.contract_address -@router.get("/api/check-user") -async def check_user(request: Request, wallet_id: str) -> dict: +@router.get("/api/check-user", response_model=DeploymentStatus) +async def check_user(request: Request, wallet_id: str) -> DeploymentStatus: """ Add a user to the database. :param request: Request object + :param wallet_id: str :return: dict """ user = user_db.get_user_by_wallet_id(wallet_id) @@ -38,8 +43,8 @@ async def check_user(request: Request, wallet_id: str) -> dict: return {"is_contract_deployed": True} -@router.post("/api/update-user-contract") -async def change_user_contract(data: UpdateUserContractRequest) -> dict: +@router.post("/api/update-user-contract", response_model=DeploymentStatus) +async def change_user_contract(data: UpdateUserContractRequest) -> DeploymentStatus: """ Change the contract status of a user. :param data: UpdateUserContractRequest @@ -53,8 +58,8 @@ async def change_user_contract(data: UpdateUserContractRequest) -> dict: return {"is_contract_deployed": False} -@router.get("/api/get-user-contract-address") -async def get_user_contract_address(wallet_id: str) -> dict: +@router.get("/api/get-user-contract-address", response_model=ContractAddress) +async def get_user_contract_address(wallet_id: str) -> ContractAddress: """ Get the contract address of a user. :param wallet_id: wallet id From de7c7a01154b0dca60bb587d4eb6ffdefddb7df8 Mon Sep 17 00:00:00 2001 From: UzNaZ Date: Sun, 20 Oct 2024 19:28:23 +0200 Subject: [PATCH 05/25] fixed alembic --- entrypoint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/entrypoint.sh b/entrypoint.sh index 19c0396d..e8237de7 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,6 +2,7 @@ echo "Run migration with alembic" alembic -c web_app/alembic.ini upgrade head +alembic -c web_app/alembic.ini upgrade heads echo "Starting the server ..." From 619a174e619fcd2b38b51b51ed19f817afa2fa09 Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 16:50:10 +0300 Subject: [PATCH 06/25] Created tests direcotry in web_app, created test_user.py file inside and made draft tests --- web_app/tests/__init__.py | 0 web_app/tests/test_user.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 web_app/tests/__init__.py create mode 100644 web_app/tests/test_user.py diff --git a/web_app/tests/__init__.py b/web_app/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py new file mode 100644 index 00000000..29939283 --- /dev/null +++ b/web_app/tests/test_user.py @@ -0,0 +1,34 @@ +import httpx +import pytest + +from ..api.main import app + +async_client = httpx.AsyncClient(app=app, base_url="http://test") + + +@pytest.mark.asyncio +async def get_user_contract_test(): + async with async_client as ac: + response = await ac.get("/api/get-user-contract") + assert response.status_code == 200 + + +@pytest.mark.asyncio +async def check_user_test(): + async with async_client as ac: + response = await ac.get("/api/check-user") + assert response.status_code == 200 + + +@pytest.mark.asyncio +async def change_user_contract_test(): + async with async_client as ac: + response = await ac.post("/api/update-user-contract") + assert response.status_code == 200 + + +@pytest.mark.asyncion +async def get_user_contract_address_test(): + async with async_client as ac: + response = await ac.get("/api/get-user-contract-address") + assert response.status_code == 200 From 8bbd9bd1484e99312f9b8b4a90d18bad05a0bc2e Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 17:55:19 +0300 Subject: [PATCH 07/25] Fixed draft tests --- web_app/tests/test_user.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py index 29939283..ef4fc16d 100644 --- a/web_app/tests/test_user.py +++ b/web_app/tests/test_user.py @@ -1,9 +1,7 @@ import httpx import pytest -from ..api.main import app - -async_client = httpx.AsyncClient(app=app, base_url="http://test") +async_client = httpx.AsyncClient(base_url="http://localhost:8000") @pytest.mark.asyncio @@ -27,7 +25,7 @@ async def change_user_contract_test(): assert response.status_code == 200 -@pytest.mark.asyncion +@pytest.mark.asyncio async def get_user_contract_address_test(): async with async_client as ac: response = await ac.get("/api/get-user-contract-address") From cf45f812ce88d2bbf3e508681158a6525cf1b3f4 Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 18:14:23 +0300 Subject: [PATCH 08/25] Created pytest.ini file --- web_app/pytest.ini | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 web_app/pytest.ini diff --git a/web_app/pytest.ini b/web_app/pytest.ini new file mode 100644 index 00000000..2f4c80e3 --- /dev/null +++ b/web_app/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +asyncio_mode = auto From b2cd1c45709a0d165dbaf606728ea9d6f911943d Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 18:14:23 +0300 Subject: [PATCH 09/25] Fixed draft tests --- web_app/tests/test_user.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py index ef4fc16d..1b6b3489 100644 --- a/web_app/tests/test_user.py +++ b/web_app/tests/test_user.py @@ -1,32 +1,33 @@ import httpx import pytest -async_client = httpx.AsyncClient(base_url="http://localhost:8000") + +@pytest.fixture(scope="function") +async def async_client(): + async with httpx.AsyncClient(base_url="http://localhost:8000") as client: + print('ggggggg\n\n\n\n\n') + yield client @pytest.mark.asyncio -async def get_user_contract_test(): - async with async_client as ac: - response = await ac.get("/api/get-user-contract") - assert response.status_code == 200 +async def test_get_user_contract(async_client): + response = await async_client.get("/api/get-user-contract") + assert response.status_code == 422 @pytest.mark.asyncio -async def check_user_test(): - async with async_client as ac: - response = await ac.get("/api/check-user") - assert response.status_code == 200 +async def test_check_user(async_client): + response = await async_client.get("/api/check-user") + assert response.status_code == 422 @pytest.mark.asyncio -async def change_user_contract_test(): - async with async_client as ac: - response = await ac.post("/api/update-user-contract") - assert response.status_code == 200 +async def test_change_user_contract(async_client): + response = await async_client.post("/api/update-user-contract") + assert response.status_code == 422 @pytest.mark.asyncio -async def get_user_contract_address_test(): - async with async_client as ac: - response = await ac.get("/api/get-user-contract-address") - assert response.status_code == 200 +async def test_get_user_contract_address(async_client): + response = await async_client.get("/api/get-user-contract-address") + assert response.status_code == 422 From 8423f7d2cd91f81da1cefab8c8a41b095d291e45 Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 18:15:10 +0300 Subject: [PATCH 10/25] Removed print debuger --- web_app/tests/test_user.py | 1 - 1 file changed, 1 deletion(-) diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py index 1b6b3489..e869a4d2 100644 --- a/web_app/tests/test_user.py +++ b/web_app/tests/test_user.py @@ -5,7 +5,6 @@ @pytest.fixture(scope="function") async def async_client(): async with httpx.AsyncClient(base_url="http://localhost:8000") as client: - print('ggggggg\n\n\n\n\n') yield client From ff59022b12387872863405f0c53411414603a5a1 Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 18:36:44 +0300 Subject: [PATCH 11/25] Created working tests --- web_app/tests/test_user.py | 56 ++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py index e869a4d2..81d4d51e 100644 --- a/web_app/tests/test_user.py +++ b/web_app/tests/test_user.py @@ -1,6 +1,8 @@ import httpx import pytest +from web_app.api.serializers.transaction import UpdateUserContractRequest + @pytest.fixture(scope="function") async def async_client(): @@ -10,23 +12,61 @@ async def async_client(): @pytest.mark.asyncio async def test_get_user_contract(async_client): - response = await async_client.get("/api/get-user-contract") - assert response.status_code == 422 + response = await async_client.get( + url="/api/get-user-contract", + params={ + "wallet_id": "", + }, + ) + response_json = response.json() + + assert response.status_code == 200 + assert isinstance(response_json, int) @pytest.mark.asyncio async def test_check_user(async_client): - response = await async_client.get("/api/check-user") - assert response.status_code == 422 + response = await async_client.get( + url="/api/check-user", + params={ + "wallet_id": "", + }, + ) + response_json = response.json() + + assert response.status_code == 200 + assert isinstance(response_json, dict) + assert "is_contract_deployed" in response_json @pytest.mark.asyncio async def test_change_user_contract(async_client): - response = await async_client.post("/api/update-user-contract") - assert response.status_code == 422 + data = UpdateUserContractRequest( + wallet_id="", + contract_address="", + ) + + response = await async_client.post( + url="/api/update-user-contract", + json=data.dict(), + ) + response_json = response.json() + + assert response.status_code == 200 + assert isinstance(response_json, dict) + assert "is_contract_deployed" in response_json @pytest.mark.asyncio async def test_get_user_contract_address(async_client): - response = await async_client.get("/api/get-user-contract-address") - assert response.status_code == 422 + response = await async_client.get( + url="/api/get-user-contract-address", + params={ + "wallet_id": "", + }, + ) + response_json = response.json() + + assert response.status_code == 200 + assert isinstance(response_json, dict) + assert "contract_address" in response_json From 437deb970dfb69f93e5de8e861ba624cc76d49cb Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Fri, 18 Oct 2024 18:51:44 +0300 Subject: [PATCH 12/25] Added pytest, pytest-asyncio and httpx --- requirements.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 56675416..1e3f01d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,7 @@ python-multipart==0.0.9 itsdangerous==2.2.0 alembic==1.13.3 psycopg2-binary==2.9.9 -SQLAlchemy==2.0.35 \ No newline at end of file +SQLAlchemy==2.0.35 +pytest==8.3.3 +pytest-asyncio==0.24.0 +httpx==0.27.2 \ No newline at end of file From f446cd07e242d6c8d6be62736b8454a01a98933e Mon Sep 17 00:00:00 2001 From: vitaliypopel Date: Sun, 20 Oct 2024 14:39:10 +0300 Subject: [PATCH 13/25] Replaced response.status_code == 200 to response.is_success --- web_app/tests/test_user.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py index 81d4d51e..aea7e57c 100644 --- a/web_app/tests/test_user.py +++ b/web_app/tests/test_user.py @@ -20,7 +20,7 @@ async def test_get_user_contract(async_client): ) response_json = response.json() - assert response.status_code == 200 + assert response.is_success assert isinstance(response_json, int) @@ -34,7 +34,7 @@ async def test_check_user(async_client): ) response_json = response.json() - assert response.status_code == 200 + assert response.is_success assert isinstance(response_json, dict) assert "is_contract_deployed" in response_json @@ -52,7 +52,7 @@ async def test_change_user_contract(async_client): ) response_json = response.json() - assert response.status_code == 200 + assert response.is_success assert isinstance(response_json, dict) assert "is_contract_deployed" in response_json @@ -67,6 +67,6 @@ async def test_get_user_contract_address(async_client): ) response_json = response.json() - assert response.status_code == 200 + assert response.is_success assert isinstance(response_json, dict) assert "contract_address" in response_json From ff16906857bc557dd16848ab6ffc648c906dac9a Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 26 Oct 2024 20:08:57 +0530 Subject: [PATCH 14/25] merge with audit-preparation --- src/deposit.cairo | 50 +++++++++++++++++++++++++++++++++++++++++--- src/interfaces.cairo | 20 +++++++++++++++++- src/types.cairo | 14 +++++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/deposit.cairo b/src/deposit.cairo index f0cca510..78a279c9 100644 --- a/src/deposit.cairo +++ b/src/deposit.cairo @@ -9,8 +9,8 @@ mod Deposit { use openzeppelin_token::erc20::interface::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait}; use spotnet::constants::ZK_SCALE_DECIMALS; - use spotnet::interfaces::{IMarketDispatcher, IMarketDispatcherTrait, IDeposit}; - use spotnet::types::{SwapData, SwapResult, DepositData}; + use spotnet::interfaces::{IMarketDispatcher, IMarketDispatcherTrait, IAirdropDispatcher, IAirdropDispatcherTrait, IDeposit}; + use spotnet::types::{SwapData, SwapResult, DepositData, Claim}; use starknet::event::EventEmitter; use starknet::storage::{StoragePointerWriteAccess, StoragePointerReadAccess}; @@ -81,11 +81,22 @@ mod Deposit { repaid_amount: u256 } + #[derive(starknet::Event, Drop)] + struct RewardClaimed { + claim_id: u64, + claimed_amount: u128, + claimee: ContractAddress, + proofs: Span, + claim_status: bool, + claim_contract: ContractAddress + } + #[event] #[derive(Drop, starknet::Event)] enum Event { LiquidityLooped: LiquidityLooped, - PositionClosed: PositionClosed + PositionClosed: PositionClosed, + RewardClaimed: RewardClaimed } #[generate_trait] @@ -325,6 +336,39 @@ mod Deposit { } ); } + + fn claim_rewards( + ref self: ContractState, + claim_data: Claim, + proofs: Span, + claim_contract: ContractAddress, + reward_token: ContractAddress + ) { + assert(self.is_position_open.read(), 'Position is not open'); + assert(proofs.len() != 0, 'Proofs Span cannot be empty'); + + let airdrop_dispatcher = IAirdropDispatcher { contract_address: claim_contract }; + let reward_dispatcher = ERC20ABIDispatcher { contract_address: reward_token }; + + let res = airdrop_dispatcher.claim(claim_data, proofs); + assert(res, 'Claim failed'); + + let send_res = reward_dispatcher.transfer(claim_data.claimee, claim_data.amount.into()); + + assert(send_res, 'Transfer failed'); + + self + .emit( + RewardClaimed { + claim_id: claim_data.id, + claimed_amount: claim_data.amount, + claimee: claim_data.claimee, + proofs, + claim_status: res, + claim_contract + } + ); + } } #[abi(embed_v0)] diff --git a/src/interfaces.cairo b/src/interfaces.cairo index 15596205..6e4ba9e7 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -1,5 +1,5 @@ use ekubo::types::keys::PoolKey; -use spotnet::types::{MarketReserveData, DepositData}; +use spotnet::types::{MarketReserveData, DepositData, Config, Claim}; use starknet::{ContractAddress}; #[starknet::interface] @@ -20,6 +20,14 @@ pub trait IDeposit { supply_price: u256, debt_price: u256 ); + + fn claim_rewards( + ref self: TContractState, + claim_data: Claim, + proofs: Span, + claim_contract: ContractAddress, + reward_token: ContractAddress + ); } #[starknet::interface] @@ -38,3 +46,13 @@ pub trait IMarket { fn repay(ref self: TContractState, token: ContractAddress, amount: felt252); fn repay_all(ref self: TContractState, token: ContractAddress); } + +#[starknet::interface] +pub trait IAirdrop { + fn get_token(self: @TContractState) -> ContractAddress; + fn get_config(self: @TContractState) -> Config; + fn claim(ref self: TContractState, claim: Claim, proof: Span) -> bool; + fn claim_128(ref self: TContractState, claims: Span, remaining_proof: Span) -> u8; + fn is_claimed(self: @TContractState, claim_id: u64) -> bool; + fn refund(ref self: TContractState); +} \ No newline at end of file diff --git a/src/types.cairo b/src/types.cairo index 67563690..1616479f 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -45,3 +45,17 @@ pub struct MarketReserveData { liquidation_bonus: felt252, debt_limit: felt252 } + +#[derive(Copy, Drop, Serde)] +pub struct Config { + root: felt252, + refundable_timestamp: u64, + refund_to: ContractAddress +} + +#[derive(Copy, Drop, Serde)] +pub struct Claim { + pub id: u64, + pub claimee: ContractAddress, + pub amount: u128 +} \ No newline at end of file From 7765235ece1e24e36c19b3c67d3eb1d64f890f22 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 26 Oct 2024 20:51:54 +0530 Subject: [PATCH 15/25] dependency error fix --- Scarb.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scarb.toml b/Scarb.toml index da783adb..0b9d8037 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -2,12 +2,12 @@ name = "spotnet" version = "0.1.0" edition = "2024_07" -cairo-version = "2.8.4" +cairo-version = "2.8.2" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -starknet = "2.8.4" +starknet = "2.8.2" ekubo = { git = "https://github.com/ekuboprotocol/abis", rev = "edb6de8" } alexandria_math = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "8208871" } openzeppelin_token = "0.17.0" From d05c6b69bd1539ddf63403dd21335196c6142fd0 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 26 Oct 2024 21:25:08 +0530 Subject: [PATCH 16/25] fix conflicts --- entrypoint.sh | 1 - .../src/pages/spotnet/dashboard/Dashboard.jsx | 59 +++++++-------- requirements.txt | 5 +- tests/test_loop.cairo | 6 ++ web_app/api/dashboard.py | 20 ++---- web_app/api/serializers/dashboard.py | 12 +--- web_app/api/serializers/transaction.py | 12 +--- web_app/api/user.py | 31 ++++---- web_app/pytest.ini | 2 - web_app/tests/__init__.py | 0 web_app/tests/test_user.py | 72 ------------------- 11 files changed, 62 insertions(+), 158 deletions(-) delete mode 100644 web_app/pytest.ini delete mode 100644 web_app/tests/__init__.py delete mode 100644 web_app/tests/test_user.py diff --git a/entrypoint.sh b/entrypoint.sh index e8237de7..19c0396d 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,7 +2,6 @@ echo "Run migration with alembic" alembic -c web_app/alembic.ini upgrade head -alembic -c web_app/alembic.ini upgrade heads echo "Starting the server ..." diff --git a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx index 79a852c3..a62213db 100644 --- a/frontend/src/pages/spotnet/dashboard/Dashboard.jsx +++ b/frontend/src/pages/spotnet/dashboard/Dashboard.jsx @@ -50,6 +50,7 @@ const Dashboard = ({ walletId }) => { const [cardData, setCardData] = useState([]); const [healthFactor, setHealthFactor] = useState(null); const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); const starData = [ { top: 1, left: 0, size: 1.5 }, { top: 75, left: 35, size: 2.5 }, @@ -57,10 +58,10 @@ const Dashboard = ({ walletId }) => { ]; useEffect(() => { - const getData = async () => { if (!walletId) { console.error("getData: walletId is undefined"); + setError(true); setLoading(false); return; } @@ -68,8 +69,7 @@ const Dashboard = ({ walletId }) => { const data = await fetchCardData({ walletId }); if (data && data.zklend_position && data.zklend_position.products) { const positions = data.zklend_position.products[0].positions || []; - const healthRatio = data.zklend_position.products[0].health_ratio; - console.log("Positions:", positions); + const healthRatio = data.zklend_position.products[0].health_ratio || 0; const cardData = positions.map((position, index) => { const isFirstCard = index === 0; @@ -80,7 +80,7 @@ const Dashboard = ({ walletId }) => { return { title: "Collateral & Earnings", icon: CollateralIcon, - balance: position.totalBalances[Object.keys(position.totalBalances)[0]], + balance: position.totalBalances[Object.keys(position.totalBalances)[0]] || 0, currencyName: isEthereum ? "Ethereum" : "STRK", currencyIcon: isEthereum ? EthIcon : StrkIcon, }; @@ -89,7 +89,7 @@ const Dashboard = ({ walletId }) => { return { title: "Borrow", icon: BorrowIcon, - balance: position.totalBalances[Object.keys(position.totalBalances)[0]], + balance: position.totalBalances[Object.keys(position.totalBalances)[0]] || 0, currencyName: "USD Coin", currencyIcon: UsdIcon, }; @@ -97,35 +97,38 @@ const Dashboard = ({ walletId }) => { setCardData(cardData); setHealthFactor(healthRatio); + setError(false); } else { console.error("Data is missing or incorrectly formatted"); - setCardData([{ - title: "Collateral & Earnings", - icon: CollateralIcon, - balance: '0.00', - currencyName: 'Ethereum', - currencyIcon: EthIcon, - }, - { - title: "Borrow", - icon: BorrowIcon, - balance: '0.00', - currencyName: 'USD Coin', - currencyIcon: UsdIcon, - },]); - setHealthFactor('0.00'); + setError(true); + setCardData([]); + setHealthFactor(0); } setLoading(false); }; + const timeoutId = setTimeout(() => { + if (loading) { + setError(true); + setLoading(false); + setCardData([]); + setHealthFactor(0); + } + }, 10000); + getData(); + return () => clearTimeout(timeoutId); }, [walletId]); if (loading) { return
Loading...
; } + if (error || !cardData.length) { + return
Error during getting the data. Please try again later.
; + } + return (
{starData.map((star, index) => ( @@ -181,17 +184,17 @@ const Dashboard = ({ walletId }) => {
+
+ +
))} -
- -
); }; diff --git a/requirements.txt b/requirements.txt index 1e3f01d3..56675416 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,4 @@ python-multipart==0.0.9 itsdangerous==2.2.0 alembic==1.13.3 psycopg2-binary==2.9.9 -SQLAlchemy==2.0.35 -pytest==8.3.3 -pytest-asyncio==0.24.0 -httpx==0.27.2 \ No newline at end of file +SQLAlchemy==2.0.35 \ No newline at end of file diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index fcfcfa86..fbe10c45 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -500,6 +500,12 @@ fn test_close_position_amounts_cleared() { assert(ERC20ABIDispatcher {contract_address: zk_market.get_reserve_data(usdc_addr).z_token_address}.balanceOf(deposit_disp.contract_address) == 0, 'Not all withdrawn'); } +#[test] +#[fork("MAINNET)] +fn test_claim_rewards() { + +} + // TODO: Calculate interest rates to test behaviour after liquidation. // #[test] diff --git a/web_app/api/dashboard.py b/web_app/api/dashboard.py index 196e7675..ab79fb34 100644 --- a/web_app/api/dashboard.py +++ b/web_app/api/dashboard.py @@ -2,32 +2,26 @@ from fastapi import APIRouter from starlette.requests import Request -from web_app.api.serializers.dashboard import Dashboard -from web_app.contract_tools.mixins.dashboard import DashboardMixin + from web_app.db.crud import PositionDBConnector +from web_app.contract_tools.mixins.dashboard import DashboardMixin router = APIRouter() position_db_connector = PositionDBConnector() -@router.get("/api/dashboard", response_model=Dashboard) -async def get_dashboard(request: Request, wallet_id: str) -> Dashboard: +@router.get("/api/dashboard") +async def get_dashboard(request: Request, wallet_id: str) -> dict: """ Get the dashboard with the balances, multipliers, start dates, and zkLend position. :param wallet_id: Wallet ID :param request: HTTP request :return: template response """ - contract_address = position_db_connector.get_contract_address_by_wallet_id( - wallet_id - ) + contract_address = position_db_connector.get_contract_address_by_wallet_id(wallet_id) opened_positions = position_db_connector.get_positions_by_wallet_id(wallet_id) - first_opened_position = ( - opened_positions[0] - if opened_positions - else collections.defaultdict(lambda: None) - ) + first_opened_position = opened_positions[0] if opened_positions else collections.defaultdict(lambda: None) # Fetch zkLend position for the wallet ID zklend_position = await DashboardMixin.get_zklend_position(contract_address) @@ -38,4 +32,4 @@ async def get_dashboard(request: Request, wallet_id: str) -> Dashboard: "multipliers": {"ETH": first_opened_position["multiplier"]}, "start_dates": {"ETH": first_opened_position["created_at"]}, "zklend_position": zklend_position, - } + } \ No newline at end of file diff --git a/web_app/api/serializers/dashboard.py b/web_app/api/serializers/dashboard.py index 10d41d09..188c6fe8 100644 --- a/web_app/api/serializers/dashboard.py +++ b/web_app/api/serializers/dashboard.py @@ -1,7 +1,8 @@ from decimal import Decimal from typing import Dict, List, Optional -from pydantic import BaseModel, Field, RootModel, validator +from pydantic import BaseModel, RootModel, Field, validator + from web_app.contract_tools.constants import TokenParams @@ -65,11 +66,4 @@ def convert_products(cls, products): return converted_products class Config: - populate_by_name = True - - -class Dashboard(BaseModel): - balances: dict[str, str] - multipliers: dict[str, list] - start_dates: dict[str, list] - zklend_position: ZkLendPositionResponse + populate_by_name = True \ No newline at end of file diff --git a/web_app/api/serializers/transaction.py b/web_app/api/serializers/transaction.py index 2a450b0e..70b701d6 100644 --- a/web_app/api/serializers/transaction.py +++ b/web_app/api/serializers/transaction.py @@ -65,7 +65,6 @@ class RepayTransactionDataResponse(BaseModel): """ Pydantic model for the repay transaction data response. """ - supply_token: str debt_token: str pool_key: PoolKey @@ -79,14 +78,5 @@ class UpdateUserContractRequest(BaseModel): """ Pydantic model for the update user contract request. """ - wallet_id: str - contract_address: str - - -class DeploymentStatus(BaseModel): - is_contract_deployed: bool - - -class ContractAddress(BaseModel): - contract_address: str | None + contract_address: str \ No newline at end of file diff --git a/web_app/api/user.py b/web_app/api/user.py index b88edc9b..ef6e447f 100644 --- a/web_app/api/user.py +++ b/web_app/api/user.py @@ -1,36 +1,31 @@ -from typing import Literal - from fastapi import APIRouter, Request -from web_app.api.serializers.transaction import (ContractAddress, - DeploymentStatus, - UpdateUserContractRequest) from web_app.db.crud import UserDBConnector +from web_app.api.serializers.transaction import UpdateUserContractRequest router = APIRouter() # Initialize the router user_db = UserDBConnector() -@router.get("/api/get-user-contract", response_model=str) -async def get_user_contract(wallet_id: str) -> str: +@router.get("/api/get-user-contract") +async def get_user_contract(wallet_id: str) -> int: """ Get the contract status of a user. :param wallet_id: wallet id - :return: str + :return: int """ user = user_db.get_user_by_wallet_id(wallet_id) if user is None or not user.is_contract_deployed: - return "" + return 0 else: - return user.contract_address + return user.deployed_transaction_hash -@router.get("/api/check-user", response_model=DeploymentStatus) -async def check_user(request: Request, wallet_id: str) -> DeploymentStatus: +@router.get("/api/check-user") +async def check_user(request: Request, wallet_id: str) -> dict: """ Add a user to the database. :param request: Request object - :param wallet_id: str :return: dict """ user = user_db.get_user_by_wallet_id(wallet_id) @@ -43,8 +38,8 @@ async def check_user(request: Request, wallet_id: str) -> DeploymentStatus: return {"is_contract_deployed": True} -@router.post("/api/update-user-contract", response_model=DeploymentStatus) -async def change_user_contract(data: UpdateUserContractRequest) -> DeploymentStatus: +@router.post("/api/update-user-contract") +async def change_user_contract(data: UpdateUserContractRequest) -> dict: """ Change the contract status of a user. :param data: UpdateUserContractRequest @@ -58,8 +53,8 @@ async def change_user_contract(data: UpdateUserContractRequest) -> DeploymentSta return {"is_contract_deployed": False} -@router.get("/api/get-user-contract-address", response_model=ContractAddress) -async def get_user_contract_address(wallet_id: str) -> ContractAddress: +@router.get("/api/get-user-contract-address") +async def get_user_contract_address(wallet_id: str) -> dict: """ Get the contract address of a user. :param wallet_id: wallet id @@ -69,4 +64,4 @@ async def get_user_contract_address(wallet_id: str) -> ContractAddress: if contract_address: return {"contract_address": contract_address} else: - return {"contract_address": None} + return {"contract_address": None} \ No newline at end of file diff --git a/web_app/pytest.ini b/web_app/pytest.ini deleted file mode 100644 index 2f4c80e3..00000000 --- a/web_app/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -asyncio_mode = auto diff --git a/web_app/tests/__init__.py b/web_app/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/web_app/tests/test_user.py b/web_app/tests/test_user.py deleted file mode 100644 index aea7e57c..00000000 --- a/web_app/tests/test_user.py +++ /dev/null @@ -1,72 +0,0 @@ -import httpx -import pytest - -from web_app.api.serializers.transaction import UpdateUserContractRequest - - -@pytest.fixture(scope="function") -async def async_client(): - async with httpx.AsyncClient(base_url="http://localhost:8000") as client: - yield client - - -@pytest.mark.asyncio -async def test_get_user_contract(async_client): - response = await async_client.get( - url="/api/get-user-contract", - params={ - "wallet_id": "", - }, - ) - response_json = response.json() - - assert response.is_success - assert isinstance(response_json, int) - - -@pytest.mark.asyncio -async def test_check_user(async_client): - response = await async_client.get( - url="/api/check-user", - params={ - "wallet_id": "", - }, - ) - response_json = response.json() - - assert response.is_success - assert isinstance(response_json, dict) - assert "is_contract_deployed" in response_json - - -@pytest.mark.asyncio -async def test_change_user_contract(async_client): - data = UpdateUserContractRequest( - wallet_id="", - contract_address="", - ) - - response = await async_client.post( - url="/api/update-user-contract", - json=data.dict(), - ) - response_json = response.json() - - assert response.is_success - assert isinstance(response_json, dict) - assert "is_contract_deployed" in response_json - - -@pytest.mark.asyncio -async def test_get_user_contract_address(async_client): - response = await async_client.get( - url="/api/get-user-contract-address", - params={ - "wallet_id": "", - }, - ) - response_json = response.json() - - assert response.is_success - assert isinstance(response_json, dict) - assert "contract_address" in response_json From c9ab4c32dd1e9c33b76fda900c7564bb1c2ec076 Mon Sep 17 00:00:00 2001 From: Sagar Rana Date: Sat, 26 Oct 2024 21:27:54 +0530 Subject: [PATCH 17/25] fix conflict --- web_app/api/dashboard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web_app/api/dashboard.py b/web_app/api/dashboard.py index ab79fb34..bd69bc26 100644 --- a/web_app/api/dashboard.py +++ b/web_app/api/dashboard.py @@ -32,4 +32,5 @@ async def get_dashboard(request: Request, wallet_id: str) -> dict: "multipliers": {"ETH": first_opened_position["multiplier"]}, "start_dates": {"ETH": first_opened_position["created_at"]}, "zklend_position": zklend_position, - } \ No newline at end of file + } + From b2db2a72eb9e3b6c6b7766676cc96c3cd9203b0e Mon Sep 17 00:00:00 2001 From: Sagar Rana Date: Sat, 26 Oct 2024 21:28:51 +0530 Subject: [PATCH 18/25] fix --- web_app/api/dashboard.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web_app/api/dashboard.py b/web_app/api/dashboard.py index bd69bc26..a22a4ca6 100644 --- a/web_app/api/dashboard.py +++ b/web_app/api/dashboard.py @@ -32,5 +32,4 @@ async def get_dashboard(request: Request, wallet_id: str) -> dict: "multipliers": {"ETH": first_opened_position["multiplier"]}, "start_dates": {"ETH": first_opened_position["created_at"]}, "zklend_position": zklend_position, - } - + } From 9c5f9dd41986a738a9b082d3f626070bc7fd27bc Mon Sep 17 00:00:00 2001 From: Sagar Rana Date: Sat, 26 Oct 2024 21:30:56 +0530 Subject: [PATCH 19/25] fix conflict --- web_app/api/dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_app/api/dashboard.py b/web_app/api/dashboard.py index a22a4ca6..04292a1f 100644 --- a/web_app/api/dashboard.py +++ b/web_app/api/dashboard.py @@ -32,4 +32,4 @@ async def get_dashboard(request: Request, wallet_id: str) -> dict: "multipliers": {"ETH": first_opened_position["multiplier"]}, "start_dates": {"ETH": first_opened_position["created_at"]}, "zklend_position": zklend_position, - } + } From 06c1ed47ff1078a4a6ff32066fb5928a7eda1c3e Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 26 Oct 2024 21:32:53 +0530 Subject: [PATCH 20/25] merge conflict --- web_app/api/serializers/dashboard.py | 2 +- web_app/api/serializers/transaction.py | 2 +- web_app/api/user.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web_app/api/serializers/dashboard.py b/web_app/api/serializers/dashboard.py index 188c6fe8..3fb49325 100644 --- a/web_app/api/serializers/dashboard.py +++ b/web_app/api/serializers/dashboard.py @@ -66,4 +66,4 @@ def convert_products(cls, products): return converted_products class Config: - populate_by_name = True \ No newline at end of file + populate_by_name = True diff --git a/web_app/api/serializers/transaction.py b/web_app/api/serializers/transaction.py index 70b701d6..1c392260 100644 --- a/web_app/api/serializers/transaction.py +++ b/web_app/api/serializers/transaction.py @@ -79,4 +79,4 @@ class UpdateUserContractRequest(BaseModel): Pydantic model for the update user contract request. """ wallet_id: str - contract_address: str \ No newline at end of file + contract_address: str diff --git a/web_app/api/user.py b/web_app/api/user.py index ef6e447f..7fbc96b0 100644 --- a/web_app/api/user.py +++ b/web_app/api/user.py @@ -64,4 +64,4 @@ async def get_user_contract_address(wallet_id: str) -> dict: if contract_address: return {"contract_address": contract_address} else: - return {"contract_address": None} \ No newline at end of file + return {"contract_address": None} From 0b68f307e83aeb1b35de436e9201a98f8a062a32 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Mon, 28 Oct 2024 03:55:35 +0530 Subject: [PATCH 21/25] added tests --- src/deposit.cairo | 13 ++- src/interfaces.cairo | 7 +- src/types.cairo | 2 +- tests/interfaces.cairo | 4 +- tests/test_loop.cairo | 199 ++++++++++++++++++++++++++++++----------- 5 files changed, 161 insertions(+), 64 deletions(-) diff --git a/src/deposit.cairo b/src/deposit.cairo index 78a279c9..c9909144 100644 --- a/src/deposit.cairo +++ b/src/deposit.cairo @@ -9,7 +9,10 @@ mod Deposit { use openzeppelin_token::erc20::interface::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait}; use spotnet::constants::ZK_SCALE_DECIMALS; - use spotnet::interfaces::{IMarketDispatcher, IMarketDispatcherTrait, IAirdropDispatcher, IAirdropDispatcherTrait, IDeposit}; + use spotnet::interfaces::{ + IMarketDispatcher, IMarketDispatcherTrait, IAirdropDispatcher, IAirdropDispatcherTrait, + IDeposit + }; use spotnet::types::{SwapData, SwapResult, DepositData, Claim}; use starknet::event::EventEmitter; @@ -342,21 +345,15 @@ mod Deposit { claim_data: Claim, proofs: Span, claim_contract: ContractAddress, - reward_token: ContractAddress ) { assert(self.is_position_open.read(), 'Position is not open'); assert(proofs.len() != 0, 'Proofs Span cannot be empty'); let airdrop_dispatcher = IAirdropDispatcher { contract_address: claim_contract }; - let reward_dispatcher = ERC20ABIDispatcher { contract_address: reward_token }; let res = airdrop_dispatcher.claim(claim_data, proofs); assert(res, 'Claim failed'); - let send_res = reward_dispatcher.transfer(claim_data.claimee, claim_data.amount.into()); - - assert(send_res, 'Transfer failed'); - self .emit( RewardClaimed { @@ -368,7 +365,7 @@ mod Deposit { claim_contract } ); - } + } } #[abi(embed_v0)] diff --git a/src/interfaces.cairo b/src/interfaces.cairo index 6e4ba9e7..e29c31f6 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -26,7 +26,6 @@ pub trait IDeposit { claim_data: Claim, proofs: Span, claim_contract: ContractAddress, - reward_token: ContractAddress ); } @@ -52,7 +51,9 @@ pub trait IAirdrop { fn get_token(self: @TContractState) -> ContractAddress; fn get_config(self: @TContractState) -> Config; fn claim(ref self: TContractState, claim: Claim, proof: Span) -> bool; - fn claim_128(ref self: TContractState, claims: Span, remaining_proof: Span) -> u8; + fn claim_128( + ref self: TContractState, claims: Span, remaining_proof: Span + ) -> u8; fn is_claimed(self: @TContractState, claim_id: u64) -> bool; fn refund(ref self: TContractState); -} \ No newline at end of file +} diff --git a/src/types.cairo b/src/types.cairo index 1616479f..1cf8ffab 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -58,4 +58,4 @@ pub struct Claim { pub id: u64, pub claimee: ContractAddress, pub amount: u128 -} \ No newline at end of file +} diff --git a/tests/interfaces.cairo b/tests/interfaces.cairo index 05760092..71ef427a 100644 --- a/tests/interfaces.cairo +++ b/tests/interfaces.cairo @@ -1,5 +1,5 @@ -use starknet::ContractAddress; use spotnet::types::MarketReserveData; +use starknet::ContractAddress; #[starknet::interface] pub trait IMarketTesting { @@ -7,7 +7,7 @@ pub trait IMarketTesting { fn get_user_debt_for_token( self: @TContractState, user: ContractAddress, token: ContractAddress ) -> felt252; - + fn liquidate( ref self: TContractState, user: ContractAddress, diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index fbe10c45..b3cbde70 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -18,15 +18,14 @@ use snforge_std::cheatcodes::execution_info::caller_address::{ }; use snforge_std::{declare, DeclareResultTrait, ContractClassTrait}; use spotnet::interfaces::{ - IDepositDispatcher, IDepositSafeDispatcher, IDepositSafeDispatcherTrait, - IDepositDispatcherTrait + IDepositDispatcher, IDepositSafeDispatcher, IDepositSafeDispatcherTrait, IDepositDispatcherTrait }; -use spotnet::types::{DepositData}; - -use super::interfaces::{IMarketTestingDispatcher, IMarketTestingDispatcherTrait}; +use spotnet::types::{DepositData, Claim}; use starknet::{ContractAddress, get_caller_address, get_block_number, get_block_timestamp}; +use super::interfaces::{IMarketTestingDispatcher, IMarketTestingDispatcherTrait}; + mod contracts { pub const EKUBO_CORE_MAINNET: felt252 = 0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b; @@ -92,8 +91,7 @@ fn test_loop_eth_valid() { 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 .try_into() .unwrap(); - let user: ContractAddress = - 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff + let user: ContractAddress = 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff .try_into() .unwrap(); @@ -135,8 +133,7 @@ fn test_loop_eth_fuzz(amount: u64) { 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 .try_into() .unwrap(); - let user: ContractAddress = - 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff + let user: ContractAddress = 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff .try_into() .unwrap(); let pool_key = PoolKey { @@ -163,14 +160,14 @@ fn test_loop_eth_fuzz(amount: u64) { pool_price, pool_price ) { - let message = *panic_data.at(0); - assert( - message == 'Parameters cannot be zero' - || message == 'Loop amount is too small' - || message == 'Approved amount incuficient' - || message == 'Insufficient balance', - message - ); // Acceptable panics which can be triggered by fuzzers' values + let message = *panic_data.at(0); + assert( + message == 'Parameters cannot be zero' + || message == 'Loop amount is too small' + || message == 'Approved amount incuficient' + || message == 'Insufficient balance', + message + ); // Acceptable panics which can be triggered by fuzzers' values }; stop_cheat_account_contract_address(deposit_disp.contract_address); } @@ -331,8 +328,7 @@ fn test_loop_position_exists_fuzz(amount: u64) { 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 .try_into() .unwrap(); - let user: ContractAddress = - 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff + let user: ContractAddress = 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff .try_into() .unwrap(); let pool_key = PoolKey { @@ -362,15 +358,17 @@ fn test_loop_position_exists_fuzz(amount: u64) { ) { return; }; - match deposit_disp.loop_liquidity( - DepositData { token: eth_addr, amount: amount.into(), multiplier: 2 }, - pool_key, - pool_price, - pool_price - ) { + match deposit_disp + .loop_liquidity( + DepositData { token: eth_addr, amount: amount.into(), multiplier: 2 }, + pool_key, + pool_price, + pool_price + ) { Result::Ok(_) => panic_with_felt252('Not panicked with position open'), - Result::Err(panic_data) => assert(*panic_data.at(0) == 'Open position already exists', - *panic_data.at(0)) + Result::Err(panic_data) => assert( + *panic_data.at(0) == 'Open position already exists', *panic_data.at(0) + ) }; stop_cheat_account_contract_address(deposit_disp.contract_address); } @@ -423,26 +421,30 @@ fn test_close_position_usdc_valid_time_passed() { pool_price ); stop_cheat_account_contract_address(deposit_disp.contract_address); - let zk_market = IMarketTestingDispatcher {contract_address: contracts::ZKLEND_MARKET.try_into().unwrap()}; + let zk_market = IMarketTestingDispatcher { + contract_address: contracts::ZKLEND_MARKET.try_into().unwrap() + }; let usdc_reserve = zk_market.get_reserve_data(usdc_addr); let eth_reserve = zk_market.get_reserve_data(eth_addr); - let (lending_rate, borrowing_rate): (u256, u256) = (usdc_reserve.current_lending_rate.into(), eth_reserve.current_borrowing_rate.into()); + let (lending_rate, borrowing_rate): (u256, u256) = ( + usdc_reserve.current_lending_rate.into(), eth_reserve.current_borrowing_rate.into() + ); // println!("{}", lending_rate); // println!("{}", borrowing_rate); start_cheat_account_contract_address(deposit_disp.contract_address, user); start_cheat_block_timestamp( contracts::ZKLEND_MARKET.try_into().unwrap(), get_block_timestamp() + 40000000 ); - // println!("Debt {}", zk_market.get_user_debt_for_token(deposit_disp.contract_address, eth_addr)); - // println!("Z bal {}", ERC20ABIDispatcher {contract_address: usdc_reserve.z_token_address}.balanceOf(deposit_disp.contract_address)); + // println!("Debt {}", zk_market.get_user_debt_for_token(deposit_disp.contract_address, + // eth_addr)); + // println!("Z bal {}", ERC20ABIDispatcher {contract_address: + // usdc_reserve.z_token_address}.balanceOf(deposit_disp.contract_address)); deposit_disp.close_position(usdc_addr, eth_addr, pool_key, pool_price, quote_token_price); stop_cheat_block_timestamp(contracts::ZKLEND_MARKET.try_into().unwrap()); stop_cheat_account_contract_address(deposit_disp.contract_address); // println!("After bal {}", token_disp.balanceOf(user)); - assert( - token_disp.balanceOf(user) > initial_balance, 'Balance is in wrong state' - ); + assert(token_disp.balanceOf(user) > initial_balance, 'Balance is in wrong state'); } #[test] @@ -491,21 +493,110 @@ fn test_close_position_amounts_cleared() { pool_price ); stop_cheat_account_contract_address(deposit_disp.contract_address); - let zk_market = IMarketTestingDispatcher {contract_address: contracts::ZKLEND_MARKET.try_into().unwrap()}; + let zk_market = IMarketTestingDispatcher { + contract_address: contracts::ZKLEND_MARKET.try_into().unwrap() + }; start_cheat_account_contract_address(deposit_disp.contract_address, user); deposit_disp.close_position(usdc_addr, eth_addr, pool_key, pool_price, quote_token_price); stop_cheat_account_contract_address(deposit_disp.contract_address); - - assert(zk_market.get_user_debt_for_token(deposit_disp.contract_address, eth_addr) == 0, 'Debt remains after repay'); - assert(ERC20ABIDispatcher {contract_address: zk_market.get_reserve_data(usdc_addr).z_token_address}.balanceOf(deposit_disp.contract_address) == 0, 'Not all withdrawn'); + + assert( + zk_market.get_user_debt_for_token(deposit_disp.contract_address, eth_addr) == 0, + 'Debt remains after repay' + ); + assert( + ERC20ABIDispatcher { + contract_address: zk_market.get_reserve_data(usdc_addr).z_token_address + } + .balanceOf(deposit_disp.contract_address) == 0, + 'Not all withdrawn' + ); } #[test] -#[fork("MAINNET)] +#[fork("MAINNET", block_number: 834899)] fn test_claim_rewards() { - -} + let strk_addr: ContractAddress = + 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d + .try_into() + .unwrap(); + + let usdc_addr: ContractAddress = + 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8 + .try_into() + .unwrap(); + let eth_addr: ContractAddress = + 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 + .try_into() + .unwrap(); + + let airdrop_addr: ContractAddress = + 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c + .try_into() + .unwrap(); + + let user: ContractAddress = 0x20281104e6cb5884dabcdf3be376cf4ff7b680741a7bb20e5e07c26cd4870af + .try_into() + .unwrap(); + + let pool_key = PoolKey { + token0: eth_addr, + token1: usdc_addr, + fee: 170141183460469235273462165868118016, + tick_spacing: 1000, + extension: 0.try_into().unwrap() + }; + + let claim_data = Claim { id: 10611, claimee: user, amount: 0x2d86724a27dc3e2 }; + + let proofs = [ + 0x5e3a0851fc0f58fc98964fa4aeccfae6170f87540fb6c98c6b1a95ff8619235, + 0x2d6dc4884ec2fe892aeb92c661de4bd41a833603f309a2ca4079647f8bfc2d1, + 0x73a528ae05f2995cfecb744ffd6a9dd8e4697fb5fd65a6ee8bcdf3f7dba924d, + 0x6d4d65e6140674f5aa8aad2da4110faec2aba7a4b80080468a5068b5d8bfa55, + 0x58d3abc98b3aad194393f72f3be4f71636b2af39272e1ac4cae588ac5569e95, + 0x2d45d9ea573b7e830e182feaaf67fb9296080cdf8877ad787e8cd13a219c187, + 0x7fdc8c1b9a2303764f692d208ba6725a57db5e542f92b4dffeaebd00b495bb9, + 0x321c1fb2c1b85728f374568de28e173a220d2e0efcc404c7a7cd39883b0c8f7, + 0x151cfa61a31b61e7e8dedb909c6dbb13259404d8f413796e1c285ef8908a18b, + 0x45cbbc33878e5728fc97fb00c722a5946087c6f2ac287a15fa5abfa407b4d7d, + 0x194a2043aff310ac94defa8f50d78d66d63076a521c5fd7e2420c9b10a66813, + 0x3877f5b4750b7cb26e211e2f867882680bf9a9542222971f048fb831e6f225a, + 0x5c4a8fbdc17983b19b841f490aa0531d274e9a42231d22be2dadfbce6cdf981, + 0x44692783f2e911b439cd018f3ba8c067ba5ab88bec4b35e2496b2a3b0f817ef + ].span(); + + let pool_price: u256 = get_asset_price_pragma('ETH/USD').into(); + + let strk_disp = ERC20ABIDispatcher { contract_address: strk_addr }; + let eth_disp = ERC20ABIDispatcher { contract_address: eth_addr }; + let deposit_disp = get_deposit_dispatcher(user); + start_cheat_caller_address(eth_addr.try_into().unwrap(), user); + eth_disp.approve(deposit_disp.contract_address, 685000000000000); + stop_cheat_caller_address(eth_addr); + + start_cheat_account_contract_address(deposit_disp.contract_address, user); + deposit_disp + .loop_liquidity( + DepositData { token: eth_addr, amount: 685000000000000, multiplier: 4 }, + pool_key, + pool_price, + pool_price + ); + stop_cheat_account_contract_address(deposit_disp.contract_address); + + let initial_balance = strk_disp.balanceOf(user); + // println!("initial bal {}", initial_balance); + + deposit_disp + .claim_rewards(claim_data: claim_data, proofs: proofs, claim_contract: airdrop_addr,); + + let final_balance = strk_disp.balanceOf(user); + // println!("final bal {}", final_balance); + + assert(final_balance > initial_balance, 'Reward was not transferred'); +} // TODO: Calculate interest rates to test behaviour after liquidation. // #[test] @@ -519,10 +610,12 @@ fn test_claim_rewards() { // 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 // .try_into() // .unwrap(); -// let user: ContractAddress = 0x0038925b0bcf4dce081042ca26a96300d9e181b910328db54a6c89e5451503f5 +// let user: ContractAddress = +// 0x0038925b0bcf4dce081042ca26a96300d9e181b910328db54a6c89e5451503f5 // .try_into() // .unwrap(); -// let liquidator: ContractAddress = 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff.try_into().unwrap(); +// let liquidator: ContractAddress = +// 0x059a943ca214c10234b9a3b61c558ac20c005127d183b86a99a8f3c60a08b4ff.try_into().unwrap(); // let pool_key = PoolKey { // token0: eth_addr, @@ -556,23 +649,28 @@ fn test_claim_rewards() { // pool_price // ); // stop_cheat_account_contract_address(deposit_disp.contract_address); -// let zk_market = IMarketTestingDispatcher {contract_address: contracts::ZKLEND_MARKET.try_into().unwrap()}; +// let zk_market = IMarketTestingDispatcher {contract_address: +// contracts::ZKLEND_MARKET.try_into().unwrap()}; // let usdc_reserve = zk_market.get_reserve_data(usdc_addr); // let eth_reserve = zk_market.get_reserve_data(eth_addr); -// let (lending_rate, borrowing_rate): (u256, u256) = (eth_reserve.current_lending_rate.into(), usdc_reserve.current_borrowing_rate.into()); +// let (lending_rate, borrowing_rate): (u256, u256) = (eth_reserve.current_lending_rate.into(), +// usdc_reserve.current_borrowing_rate.into()); // start_cheat_account_contract_address(deposit_disp.contract_address, user); -// start_cheat_block_timestamp(contracts::ZKLEND_MARKET.try_into().unwrap(), get_block_timestamp() + 4000000000); - +// start_cheat_block_timestamp(contracts::ZKLEND_MARKET.try_into().unwrap(), +// get_block_timestamp() + 4000000000); + // start_cheat_caller_address(zk_market.contract_address, liquidator); - -// let debt = zk_market.get_user_debt_for_token(deposit_disp.contract_address, usdc_addr).into(); + +// let debt = zk_market.get_user_debt_for_token(deposit_disp.contract_address, +// usdc_addr).into(); // start_cheat_caller_address(usdc_addr, liquidator); // ERC20ABIDispatcher {contract_address: usdc_addr}.approve(zk_market.contract_address, debt); // stop_cheat_caller_address(usdc_addr); -// zk_market.liquidate(deposit_disp.contract_address, usdc_addr, (debt / 4).try_into().unwrap(), eth_addr); +// zk_market.liquidate(deposit_disp.contract_address, usdc_addr, (debt / 4).try_into().unwrap(), +// eth_addr); // stop_cheat_caller_address(zk_market.contract_address); // // deposit_disp.close_position(eth_addr, usdc_addr, pool_key, pool_price, quote_token_price); @@ -580,3 +678,4 @@ fn test_claim_rewards() { // stop_cheat_account_contract_address(deposit_disp.contract_address); // } + From a4efff1da8a71adafc59a6013ecf3d53fa84afe6 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Mon, 28 Oct 2024 04:27:45 +0530 Subject: [PATCH 22/25] minor changes --- src/deposit.cairo | 34 +++++++++------------------------- src/interfaces.cairo | 7 +------ tests/test_loop.cairo | 9 ++------- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/src/deposit.cairo b/src/deposit.cairo index c9909144..1f5b5247 100644 --- a/src/deposit.cairo +++ b/src/deposit.cairo @@ -86,12 +86,7 @@ mod Deposit { #[derive(starknet::Event, Drop)] struct RewardClaimed { - claim_id: u64, - claimed_amount: u128, - claimee: ContractAddress, - proofs: Span, - claim_status: bool, - claim_contract: ContractAddress + claim_status: bool } #[event] @@ -340,31 +335,20 @@ mod Deposit { ); } - fn claim_rewards( - ref self: ContractState, - claim_data: Claim, - proofs: Span, - claim_contract: ContractAddress, - ) { + fn claim_rewards(ref self: ContractState, claim_data: Claim, proofs: Span,) { assert(self.is_position_open.read(), 'Position is not open'); assert(proofs.len() != 0, 'Proofs Span cannot be empty'); - let airdrop_dispatcher = IAirdropDispatcher { contract_address: claim_contract }; + let airdrop_addr: ContractAddress = + 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c + .try_into() + .unwrap(); + let airdrop_disp = IAirdropDispatcher { contract_address: airdrop_addr }; - let res = airdrop_dispatcher.claim(claim_data, proofs); + let res = airdrop_disp.claim(claim_data, proofs); assert(res, 'Claim failed'); - self - .emit( - RewardClaimed { - claim_id: claim_data.id, - claimed_amount: claim_data.amount, - claimee: claim_data.claimee, - proofs, - claim_status: res, - claim_contract - } - ); + self.emit(RewardClaimed { claim_status: res, }); } } diff --git a/src/interfaces.cairo b/src/interfaces.cairo index e29c31f6..2d57b163 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -21,12 +21,7 @@ pub trait IDeposit { debt_price: u256 ); - fn claim_rewards( - ref self: TContractState, - claim_data: Claim, - proofs: Span, - claim_contract: ContractAddress, - ); + fn claim_rewards(ref self: TContractState, claim_data: Claim, proofs: Span,); } #[starknet::interface] diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index b3cbde70..e5b28251 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -530,11 +530,6 @@ fn test_claim_rewards() { .try_into() .unwrap(); - let airdrop_addr: ContractAddress = - 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c - .try_into() - .unwrap(); - let user: ContractAddress = 0x20281104e6cb5884dabcdf3be376cf4ff7b680741a7bb20e5e07c26cd4870af .try_into() .unwrap(); @@ -589,8 +584,7 @@ fn test_claim_rewards() { let initial_balance = strk_disp.balanceOf(user); // println!("initial bal {}", initial_balance); - deposit_disp - .claim_rewards(claim_data: claim_data, proofs: proofs, claim_contract: airdrop_addr,); + deposit_disp.claim_rewards(claim_data: claim_data, proofs: proofs); let final_balance = strk_disp.balanceOf(user); // println!("final bal {}", final_balance); @@ -679,3 +673,4 @@ fn test_claim_rewards() { // stop_cheat_account_contract_address(deposit_disp.contract_address); // } + From 7db97d323f79937ada508633634b6c52d1b351fa Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Mon, 28 Oct 2024 14:10:43 +0530 Subject: [PATCH 23/25] additional assert to check reward amount --- tests/test_loop.cairo | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index e5b28251..7c1b5f39 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -590,6 +590,7 @@ fn test_claim_rewards() { // println!("final bal {}", final_balance); assert(final_balance > initial_balance, 'Reward was not transferred'); + assert(final_balance - initial_balance == claim_data.amount.into(), 'Unexpected amount was rewarded'); } // TODO: Calculate interest rates to test behaviour after liquidation. From ad02dd9df129e19351b56b6f909e54e5c0a1c772 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Tue, 29 Oct 2024 00:04:42 +0530 Subject: [PATCH 24/25] requested changes --- src/deposit.cairo | 19 +++---------------- src/interfaces.cairo | 11 ++--------- src/types.cairo | 7 ------- tests/test_loop.cairo | 9 +++++++-- 4 files changed, 12 insertions(+), 34 deletions(-) diff --git a/src/deposit.cairo b/src/deposit.cairo index 1f5b5247..d991dca8 100644 --- a/src/deposit.cairo +++ b/src/deposit.cairo @@ -84,17 +84,11 @@ mod Deposit { repaid_amount: u256 } - #[derive(starknet::Event, Drop)] - struct RewardClaimed { - claim_status: bool - } - #[event] #[derive(Drop, starknet::Event)] enum Event { LiquidityLooped: LiquidityLooped, PositionClosed: PositionClosed, - RewardClaimed: RewardClaimed } #[generate_trait] @@ -335,20 +329,13 @@ mod Deposit { ); } - fn claim_rewards(ref self: ContractState, claim_data: Claim, proofs: Span,) { + fn claim_rewards(ref self: ContractState, claim_data: Claim, proof: Span, airdrop_addr: ContractAddress) { assert(self.is_position_open.read(), 'Position is not open'); - assert(proofs.len() != 0, 'Proofs Span cannot be empty'); + assert(proof.len() != 0, 'Proof Span cannot be empty'); - let airdrop_addr: ContractAddress = - 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c - .try_into() - .unwrap(); let airdrop_disp = IAirdropDispatcher { contract_address: airdrop_addr }; - let res = airdrop_disp.claim(claim_data, proofs); - assert(res, 'Claim failed'); - - self.emit(RewardClaimed { claim_status: res, }); + assert(airdrop_disp.claim(claim_data, proof), 'Claim failed'); } } diff --git a/src/interfaces.cairo b/src/interfaces.cairo index 2d57b163..26f94c8e 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -1,5 +1,5 @@ use ekubo::types::keys::PoolKey; -use spotnet::types::{MarketReserveData, DepositData, Config, Claim}; +use spotnet::types::{MarketReserveData, DepositData, Claim}; use starknet::{ContractAddress}; #[starknet::interface] @@ -21,7 +21,7 @@ pub trait IDeposit { debt_price: u256 ); - fn claim_rewards(ref self: TContractState, claim_data: Claim, proofs: Span,); + fn claim_rewards(ref self: TContractState, claim_data: Claim, proof: Span, airdrop_addr: ContractAddress); } #[starknet::interface] @@ -43,12 +43,5 @@ pub trait IMarket { #[starknet::interface] pub trait IAirdrop { - fn get_token(self: @TContractState) -> ContractAddress; - fn get_config(self: @TContractState) -> Config; fn claim(ref self: TContractState, claim: Claim, proof: Span) -> bool; - fn claim_128( - ref self: TContractState, claims: Span, remaining_proof: Span - ) -> u8; - fn is_claimed(self: @TContractState, claim_id: u64) -> bool; - fn refund(ref self: TContractState); } diff --git a/src/types.cairo b/src/types.cairo index 1cf8ffab..d8d05e77 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -46,13 +46,6 @@ pub struct MarketReserveData { debt_limit: felt252 } -#[derive(Copy, Drop, Serde)] -pub struct Config { - root: felt252, - refundable_timestamp: u64, - refund_to: ContractAddress -} - #[derive(Copy, Drop, Serde)] pub struct Claim { pub id: u64, diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index 7c1b5f39..0cf6ae0d 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -530,6 +530,11 @@ fn test_claim_rewards() { .try_into() .unwrap(); + let airdrop_addr: ContractAddress = + 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c + .try_into() + .unwrap(); + let user: ContractAddress = 0x20281104e6cb5884dabcdf3be376cf4ff7b680741a7bb20e5e07c26cd4870af .try_into() .unwrap(); @@ -544,7 +549,7 @@ fn test_claim_rewards() { let claim_data = Claim { id: 10611, claimee: user, amount: 0x2d86724a27dc3e2 }; - let proofs = [ + let proof = [ 0x5e3a0851fc0f58fc98964fa4aeccfae6170f87540fb6c98c6b1a95ff8619235, 0x2d6dc4884ec2fe892aeb92c661de4bd41a833603f309a2ca4079647f8bfc2d1, 0x73a528ae05f2995cfecb744ffd6a9dd8e4697fb5fd65a6ee8bcdf3f7dba924d, @@ -584,7 +589,7 @@ fn test_claim_rewards() { let initial_balance = strk_disp.balanceOf(user); // println!("initial bal {}", initial_balance); - deposit_disp.claim_rewards(claim_data: claim_data, proofs: proofs); + deposit_disp.claim_rewards(claim_data, proof, airdrop_addr); let final_balance = strk_disp.balanceOf(user); // println!("final bal {}", final_balance); From c9cedfd78ae977edd7c4f0ee889b15d73dcad555 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Tue, 29 Oct 2024 00:07:46 +0530 Subject: [PATCH 25/25] scarb fmt --- src/deposit.cairo | 7 ++++++- src/interfaces.cairo | 7 ++++++- tests/test_loop.cairo | 11 +++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/deposit.cairo b/src/deposit.cairo index d991dca8..ca981f02 100644 --- a/src/deposit.cairo +++ b/src/deposit.cairo @@ -329,7 +329,12 @@ mod Deposit { ); } - fn claim_rewards(ref self: ContractState, claim_data: Claim, proof: Span, airdrop_addr: ContractAddress) { + fn claim_rewards( + ref self: ContractState, + claim_data: Claim, + proof: Span, + airdrop_addr: ContractAddress + ) { assert(self.is_position_open.read(), 'Position is not open'); assert(proof.len() != 0, 'Proof Span cannot be empty'); diff --git a/src/interfaces.cairo b/src/interfaces.cairo index 26f94c8e..ee5d87db 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -21,7 +21,12 @@ pub trait IDeposit { debt_price: u256 ); - fn claim_rewards(ref self: TContractState, claim_data: Claim, proof: Span, airdrop_addr: ContractAddress); + fn claim_rewards( + ref self: TContractState, + claim_data: Claim, + proof: Span, + airdrop_addr: ContractAddress + ); } #[starknet::interface] diff --git a/tests/test_loop.cairo b/tests/test_loop.cairo index 0cf6ae0d..4786e21b 100644 --- a/tests/test_loop.cairo +++ b/tests/test_loop.cairo @@ -531,9 +531,9 @@ fn test_claim_rewards() { .unwrap(); let airdrop_addr: ContractAddress = - 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c - .try_into() - .unwrap(); + 0x66cabe824da3ff583b967ce571d393e8b667b33415acc750397aa66b64a5a6c + .try_into() + .unwrap(); let user: ContractAddress = 0x20281104e6cb5884dabcdf3be376cf4ff7b680741a7bb20e5e07c26cd4870af .try_into() @@ -595,7 +595,10 @@ fn test_claim_rewards() { // println!("final bal {}", final_balance); assert(final_balance > initial_balance, 'Reward was not transferred'); - assert(final_balance - initial_balance == claim_data.amount.into(), 'Unexpected amount was rewarded'); + assert( + final_balance - initial_balance == claim_data.amount.into(), + 'Unexpected amount was rewarded' + ); } // TODO: Calculate interest rates to test behaviour after liquidation.