From 6fd133e3b0aa36fa7da097f702a0ddeee153b20b Mon Sep 17 00:00:00 2001 From: datagirl Date: Fri, 17 Jul 2026 08:37:13 +0100 Subject: [PATCH] =?UTF-8?q?=E2=80=9CThe=20backend=20finally=20learned=20to?= =?UTF-8?q?=20stop=20accepting=20nonsense=20and=20start=20returning=20it?= =?UTF-8?q?=20in=20a=20very=20organized=20box.=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/mobile-ci.yml | 57 - .github/workflows/soroban-ci.yml | 70 - .github/workflows/veilend-backend.yml | 43 - .github/workflows/web-ci.yml | 53 - .gitignore | 17 - Cargo.lock | 1864 --- Cargo.toml | 18 - README.md | 223 - legacy/README.md | 14 - legacy/docs/CONTRIBUTING_SOROBAN.md | 1086 -- .../migration/mobile-stellar-integration.md | 1428 -- .../privacy-hashing-research project 1.md | 847 - .../migration/privacy-hashing-research.md | 847 - legacy/veilend-backend/.env.example | 46 - legacy/veilend-backend/.gitignore | 56 - legacy/veilend-backend/.prettierrc | 4 - legacy/veilend-backend/README.md | 202 - legacy/veilend-backend/eslint.config.mjs | 35 - .../migrations/001_add_nonce_expires_at.sql | 3 - legacy/veilend-backend/nest-cli.json | 8 - legacy/veilend-backend/package-lock.json | 10983 ------------ legacy/veilend-backend/package.json | 85 - .../src/abis/InterestToken_ABI.json | 885 - .../src/abis/LendingPool_ABI.json | 739 - .../src/abis/PriceOracle_ABI.json | 618 - .../src/abis/ReserveData_ABI.json | 815 - .../src/abis/ShieldedPool_ABI.json | 854 - .../src/abis/VEILENDGOV_ABI.json | 484 - .../addresses-provider.controller.ts | 28 - .../addresses-provider.module.ts | 12 - .../addresses-provider.service.ts | 62 - .../dto/addresses-provider.dto.ts | 11 - .../src/app.controller.spec.ts | 22 - legacy/veilend-backend/src/app.controller.ts | 5 +- legacy/veilend-backend/src/app.module.ts | 54 +- .../src/assets/assets.controller.ts | 15 - .../src/assets/assets.module.ts | 9 - .../src/assets/assets.service.ts | 15 - .../src/auth/auth.controller.spec.ts | 18 - .../src/auth/auth.controller.ts | 31 +- .../veilend-backend/src/auth/auth.module.ts | 21 +- .../src/auth/auth.service.spec.ts | 61 - .../veilend-backend/src/auth/auth.service.ts | 62 +- .../src/auth/dto/verify.dto.ts | 4 +- .../veilend-backend/src/auth/jwt.strategy.ts | 19 - .../response-envelope.interceptor.spec.ts | 16 + .../common/response-envelope.interceptor.ts | 31 + .../src/common/validation-exception.filter.ts | 31 + .../src/common/validation.util.ts | 9 + .../src/governance/dto/governance.dto.ts | 30 - .../src/governance/governance.controller.ts | 23 - .../src/governance/governance.module.ts | 12 - .../src/governance/governance.service.ts | 51 - .../interest-token/dto/interest-token.dto.ts | 40 - .../interest-token.controller.ts | 28 - .../interest-token/interest-token.module.ts | 12 - .../interest-token/interest-token.service.ts | 62 - .../src/lending-pool/dto/lending-pool.dto.ts | 82 - .../lending-pool/lending-pool.controller.ts | 33 - .../src/lending-pool/lending-pool.module.ts | 12 - .../src/lending-pool/lending-pool.service.ts | 91 - legacy/veilend-backend/src/main.ts | 46 +- .../src/positions/positions.controller.ts | 18 - .../src/positions/positions.module.ts | 9 - .../src/positions/positions.service.ts | 28 - .../src/price-oracle/dto/price-oracle.dto.ts | 52 - .../price-oracle/price-oracle.controller.ts | 33 - .../src/price-oracle/price-oracle.module.ts | 12 - .../src/price-oracle/price-oracle.service.ts | 73 - .../src/reserve-data/dto/reserve-data.dto.ts | 46 - .../reserve-data/reserve-data.controller.ts | 28 - .../src/reserve-data/reserve-data.module.ts | 12 - .../src/reserve-data/reserve-data.service.ts | 68 - .../shielded-pool/dto/shielded-pool.dto.ts | 48 - .../shielded-pool/shielded-pool.controller.ts | 33 - .../src/shielded-pool/shielded-pool.module.ts | 12 - .../shielded-pool/shielded-pool.service.ts | 182 - .../src/starknet/starknet.module.ts | 8 - .../src/starknet/starknet.service.ts | 130 - .../src/supabase/supabase.module.ts | 11 - .../src/supabase/supabase.service.ts | 171 - .../transactions/transactions.controller.ts | 20 - .../src/transactions/transactions.module.ts | 9 - .../src/transactions/transactions.service.ts | 54 - .../src/users/users.controller.ts | 20 - .../veilend-backend/src/users/users.module.ts | 10 - .../src/users/users.service.spec.ts | 18 - .../src/users/users.service.ts | 75 - legacy/veilend-backend/supabase_schema.sql | 49 - legacy/veilend-backend/test/app.e2e-spec.ts | 25 - legacy/veilend-backend/test/jest-e2e.json | 9 - legacy/veilend-backend/tsconfig.build.json | 4 - legacy/veilend-backend/tsconfig.json | 25 - veilend-backend/.env.example | 5 - veilend-backend/.prettierrc | 4 - veilend-backend/INDEXER.md | 57 - veilend-backend/README.md | 86 - veilend-backend/eslint.config.mjs | 35 - veilend-backend/nest-cli.json | 8 - veilend-backend/package-lock.json | 13865 ---------------- veilend-backend/package.json | 84 - veilend-backend/prisma/schema.prisma | 175 - veilend-backend/src/admin/admin.controller.ts | 4 - veilend-backend/src/admin/admin.module.ts | 9 - veilend-backend/src/admin/admin.service.ts | 4 - veilend-backend/src/app.controller.spec.ts | 22 - veilend-backend/src/app.controller.ts | 21 - veilend-backend/src/app.module.ts | 47 - veilend-backend/src/app.service.ts | 8 - .../src/assets/assets.controller.ts | 4 - veilend-backend/src/assets/assets.module.ts | 9 - veilend-backend/src/assets/assets.service.ts | 4 - veilend-backend/src/auth/auth.controller.ts | 30 - veilend-backend/src/auth/auth.module.ts | 28 - veilend-backend/src/auth/auth.service.ts | 43 - veilend-backend/src/auth/dto/nonce.dto.ts | 6 - .../src/auth/dto/verify-wallet.dto.ts | 12 - .../src/common/dto/api-response.dto.ts | 37 - .../src/common/dto/page-meta.dto.ts | 24 - .../src/common/dto/page-options.dto.ts | 30 - veilend-backend/src/common/dto/page.dto.ts | 14 - veilend-backend/src/events/events.entity.ts | 13 - veilend-backend/src/indexer/indexer.config.ts | 21 - .../src/indexer/indexer.controller.ts | 67 - veilend-backend/src/indexer/indexer.module.ts | 15 - .../src/indexer/indexer.repository.ts | 203 - .../src/indexer/indexer.service.spec.ts | 243 - .../src/indexer/indexer.service.ts | 316 - veilend-backend/src/jobs/jobs.module.ts | 26 - .../src/jobs/processors/backfill.processor.ts | 30 - .../src/jobs/processors/event.processor.ts | 16 - .../src/jobs/queues/event.queue.ts | 22 - veilend-backend/src/main.ts | 8 - .../src/portfolios/portfolios.controller.ts | 15 - .../src/portfolios/portfolios.module.ts | 9 - .../src/portfolios/portfolios.service.ts | 72 - .../src/stellar/horizon.service.spec.ts | 132 - .../src/stellar/horizon.service.ts | 117 - .../src/stellar/soroban-rpc.service.spec.ts | 146 - .../src/stellar/soroban-rpc.service.ts | 126 - .../stellar/stellar-account.service.spec.ts | 182 - .../src/stellar/stellar-account.service.ts | 211 - veilend-backend/src/stellar/stellar.config.ts | 21 - veilend-backend/src/stellar/stellar.module.ts | 13 - veilend-backend/src/stellar/types.ts | 9 - .../transactions/transactions.controller.ts | 15 - .../src/transactions/transactions.module.ts | 9 - .../src/transactions/transactions.service.ts | 74 - veilend-backend/src/wallet/wallet.module.ts | 10 - veilend-backend/src/wallet/wallet.service.ts | 16 - veilend-backend/test/app.e2e-spec.ts | 29 - veilend-backend/test/jest-e2e.json | 9 - veilend-backend/tsconfig.build.json | 4 - veilend-backend/tsconfig.json | 25 - veilend-mobile/.env | 25 - veilend-mobile/.env.example | 21 - veilend-mobile/.gitignore | 41 - veilend-mobile/App.tsx | 56 - veilend-mobile/app.json | 38 - veilend-mobile/assets/adaptive-icon.png | Bin 17547 -> 0 bytes veilend-mobile/assets/favicon.png | Bin 1466 -> 0 bytes veilend-mobile/assets/icon.png | Bin 22380 -> 0 bytes veilend-mobile/assets/splash-icon.png | Bin 17547 -> 0 bytes veilend-mobile/babel.config.js | 10 - veilend-mobile/eas.json | 30 - veilend-mobile/index.js | 31 - veilend-mobile/package-lock.json | 11892 ------------- veilend-mobile/package.json | 54 - veilend-mobile/postcss.config.js | 5 - .../src/components/ErrorBoundary.tsx | 130 - .../src/components/ProtocolStatusBanners.tsx | 122 - veilend-mobile/src/data/mockData.ts | 91 - veilend-mobile/src/hooks/useStellarAuth.ts | 61 - veilend-mobile/src/navigation/index.tsx | 92 - veilend-mobile/src/screens/BorrowScreen.tsx | 269 - .../src/screens/ConnectWalletScreen.tsx | 352 - .../src/screens/DashboardScreen.tsx | 761 - veilend-mobile/src/screens/DepositScreen.tsx | 269 - veilend-mobile/src/screens/RepayScreen.tsx | 281 - veilend-mobile/src/store/store.test.ts | 106 - veilend-mobile/src/store/store.ts | 316 - .../src/types/expo-vector-icons.d.ts | 1 - veilend-mobile/src/types/nativewind-env.d.ts | 1 - veilend-mobile/src/types/zustand.d.ts | 16 - veilend-mobile/src/utils/api.ts | 54 - .../src/utils/errorReporting.test.ts | 105 - veilend-mobile/src/utils/errorReporting.ts | 277 - veilend-mobile/src/utils/helpers.ts | 4 - .../src/utils/protocolStatus.test.ts | 50 - veilend-mobile/src/utils/protocolStatus.ts | 72 - veilend-mobile/src/utils/secureStoreShim.ts | 62 - veilend-mobile/src/utils/toast.ts | 30 - veilend-mobile/tailwind.config.js | 17 - veilend-mobile/tsconfig.json | 28 - veilend-soroban/.cargo/config.toml | 4 - veilend-soroban/Cargo.lock | 1689 -- veilend-soroban/Cargo.toml | 15 - veilend-soroban/README.md | 97 - veilend-soroban/rust-toolchain.toml | 4 - veilend-soroban/src/lib.rs | 421 - ...row_exceeds_oracle_collateral_limit.1.json | 76 - .../test_borrow_with_oracle_price.1.json | 76 - .../test_configure_asset.1.json | 76 - .../test_get_oracle_price_not_set.1.json | 76 - .../test_snapshots/test_initialize.1.json | 76 - .../test_min_collateral_ratio.1.json | 76 - .../test_snapshots/test_oracle_price.1.json | 76 - .../test_oracle_price_default_to_one.1.json | 76 - .../test_set_oracle_price.1.json | 76 - ...test_set_oracle_price_invalid_price.1.json | 76 - .../test_set_oracle_price_unauthorized.1.json | 76 - ...raw_exceeds_oracle_collateral_limit.1.json | 76 - veilend-soroban/veilend_hello/Cargo.toml | 14 - veilend-soroban/veilend_hello/src/lib.rs | 31 - veilend-soroban/veilend_hello/tests/test.rs | 36 - veilend-web/.env.example | 53 - veilend-web/.gitignore | 42 - veilend-web/.prettierrc | 7 - veilend-web/AGENTS.md | 5 - veilend-web/CLAUDE.md | 1 - veilend-web/README.md | 298 - veilend-web/components.json | 25 - veilend-web/eslint.config.mjs | 18 - veilend-web/next.config.ts | 19 - veilend-web/package-lock.json | 13221 --------------- veilend-web/package.json | 41 - veilend-web/postcss.config.mjs | 7 - veilend-web/public/file.svg | 1 - veilend-web/public/globe.svg | 1 - veilend-web/public/next.svg | 1 - veilend-web/public/vercel.svg | 1 - veilend-web/public/window.svg | 1 - veilend-web/src/app/(dashboard)/page.tsx | 302 - .../src/app/api/campaign-events/route.ts | 85 - veilend-web/src/app/dashboard/error.tsx | 42 - veilend-web/src/app/dashboard/loading.tsx | 62 - veilend-web/src/app/dashboard/page.tsx | 216 - veilend-web/src/app/favicon.ico | Bin 25931 -> 0 bytes veilend-web/src/app/globals.css | 161 - veilend-web/src/app/layout.tsx | 39 - veilend-web/src/app/page.tsx | 255 - veilend-web/src/components/AmountInput.tsx | 122 - .../src/components/CampaignTracker.tsx | 14 - .../src/components/ContributorInterest.tsx | 55 - veilend-web/src/components/Layout.tsx | 122 - .../src/components/SyncStatusBadge.tsx | 100 - veilend-web/src/components/TrackedLink.tsx | 46 - veilend-web/src/components/WalletConnect.tsx | 172 - veilend-web/src/components/WalletStatus.tsx | 61 - veilend-web/src/components/ui/alert.tsx | 38 - veilend-web/src/components/ui/badge.tsx | 49 - veilend-web/src/components/ui/button.tsx | 67 - veilend-web/src/components/ui/card.tsx | 103 - veilend-web/src/components/ui/checkbox.tsx | 33 - veilend-web/src/components/ui/dialog.tsx | 165 - veilend-web/src/components/ui/input.tsx | 19 - veilend-web/src/components/ui/progress.tsx | 31 - veilend-web/src/components/ui/separator.tsx | 28 - veilend-web/src/components/ui/skeleton.tsx | 13 - veilend-web/src/context/WalletContext.tsx | 24 - veilend-web/src/hooks/useStellarWallet.ts | 118 - veilend-web/src/lib/api/dashboard.ts | 113 - veilend-web/src/lib/campaignAnalytics.ts | 57 - veilend-web/src/lib/config-validation.ts | 173 - veilend-web/src/lib/hooks/usePositionSync.ts | 124 - veilend-web/src/lib/stellar/auth.ts | 110 - veilend-web/src/lib/stellar/config.ts | 22 - veilend-web/src/lib/stellar/wallet.ts | 175 - veilend-web/src/lib/types/dashboard.ts | 34 - veilend-web/src/lib/utils.ts | 6 - veilend-web/src/lib/validation/amount.test.ts | 112 - veilend-web/src/lib/validation/amount.ts | 142 - veilend-web/tsconfig.json | 34 - 273 files changed, 166 insertions(+), 77846 deletions(-) delete mode 100644 .github/workflows/mobile-ci.yml delete mode 100644 .github/workflows/soroban-ci.yml delete mode 100644 .github/workflows/veilend-backend.yml delete mode 100644 .gitignore delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 README.md delete mode 100644 legacy/README.md delete mode 100644 legacy/docs/CONTRIBUTING_SOROBAN.md delete mode 100644 legacy/docs/migration/mobile-stellar-integration.md delete mode 100644 legacy/docs/migration/privacy-hashing-research project 1.md delete mode 100644 legacy/docs/migration/privacy-hashing-research.md delete mode 100644 legacy/veilend-backend/.env.example delete mode 100644 legacy/veilend-backend/.gitignore delete mode 100644 legacy/veilend-backend/.prettierrc delete mode 100644 legacy/veilend-backend/README.md delete mode 100644 legacy/veilend-backend/eslint.config.mjs delete mode 100644 legacy/veilend-backend/migrations/001_add_nonce_expires_at.sql delete mode 100644 legacy/veilend-backend/nest-cli.json delete mode 100644 legacy/veilend-backend/package-lock.json delete mode 100644 legacy/veilend-backend/package.json delete mode 100644 legacy/veilend-backend/src/abis/InterestToken_ABI.json delete mode 100644 legacy/veilend-backend/src/abis/LendingPool_ABI.json delete mode 100644 legacy/veilend-backend/src/abis/PriceOracle_ABI.json delete mode 100644 legacy/veilend-backend/src/abis/ReserveData_ABI.json delete mode 100644 legacy/veilend-backend/src/abis/ShieldedPool_ABI.json delete mode 100644 legacy/veilend-backend/src/abis/VEILENDGOV_ABI.json delete mode 100644 legacy/veilend-backend/src/addresses-provider/addresses-provider.controller.ts delete mode 100644 legacy/veilend-backend/src/addresses-provider/addresses-provider.module.ts delete mode 100644 legacy/veilend-backend/src/addresses-provider/addresses-provider.service.ts delete mode 100644 legacy/veilend-backend/src/addresses-provider/dto/addresses-provider.dto.ts delete mode 100644 legacy/veilend-backend/src/app.controller.spec.ts delete mode 100644 legacy/veilend-backend/src/assets/assets.controller.ts delete mode 100644 legacy/veilend-backend/src/assets/assets.module.ts delete mode 100644 legacy/veilend-backend/src/assets/assets.service.ts delete mode 100644 legacy/veilend-backend/src/auth/auth.controller.spec.ts delete mode 100644 legacy/veilend-backend/src/auth/auth.service.spec.ts delete mode 100644 legacy/veilend-backend/src/auth/jwt.strategy.ts create mode 100644 legacy/veilend-backend/src/common/response-envelope.interceptor.spec.ts create mode 100644 legacy/veilend-backend/src/common/response-envelope.interceptor.ts create mode 100644 legacy/veilend-backend/src/common/validation-exception.filter.ts create mode 100644 legacy/veilend-backend/src/common/validation.util.ts delete mode 100644 legacy/veilend-backend/src/governance/dto/governance.dto.ts delete mode 100644 legacy/veilend-backend/src/governance/governance.controller.ts delete mode 100644 legacy/veilend-backend/src/governance/governance.module.ts delete mode 100644 legacy/veilend-backend/src/governance/governance.service.ts delete mode 100644 legacy/veilend-backend/src/interest-token/dto/interest-token.dto.ts delete mode 100644 legacy/veilend-backend/src/interest-token/interest-token.controller.ts delete mode 100644 legacy/veilend-backend/src/interest-token/interest-token.module.ts delete mode 100644 legacy/veilend-backend/src/interest-token/interest-token.service.ts delete mode 100644 legacy/veilend-backend/src/lending-pool/dto/lending-pool.dto.ts delete mode 100644 legacy/veilend-backend/src/lending-pool/lending-pool.controller.ts delete mode 100644 legacy/veilend-backend/src/lending-pool/lending-pool.module.ts delete mode 100644 legacy/veilend-backend/src/lending-pool/lending-pool.service.ts delete mode 100644 legacy/veilend-backend/src/positions/positions.controller.ts delete mode 100644 legacy/veilend-backend/src/positions/positions.module.ts delete mode 100644 legacy/veilend-backend/src/positions/positions.service.ts delete mode 100644 legacy/veilend-backend/src/price-oracle/dto/price-oracle.dto.ts delete mode 100644 legacy/veilend-backend/src/price-oracle/price-oracle.controller.ts delete mode 100644 legacy/veilend-backend/src/price-oracle/price-oracle.module.ts delete mode 100644 legacy/veilend-backend/src/price-oracle/price-oracle.service.ts delete mode 100644 legacy/veilend-backend/src/reserve-data/dto/reserve-data.dto.ts delete mode 100644 legacy/veilend-backend/src/reserve-data/reserve-data.controller.ts delete mode 100644 legacy/veilend-backend/src/reserve-data/reserve-data.module.ts delete mode 100644 legacy/veilend-backend/src/reserve-data/reserve-data.service.ts delete mode 100644 legacy/veilend-backend/src/shielded-pool/dto/shielded-pool.dto.ts delete mode 100644 legacy/veilend-backend/src/shielded-pool/shielded-pool.controller.ts delete mode 100644 legacy/veilend-backend/src/shielded-pool/shielded-pool.module.ts delete mode 100644 legacy/veilend-backend/src/shielded-pool/shielded-pool.service.ts delete mode 100644 legacy/veilend-backend/src/starknet/starknet.module.ts delete mode 100644 legacy/veilend-backend/src/starknet/starknet.service.ts delete mode 100644 legacy/veilend-backend/src/supabase/supabase.module.ts delete mode 100644 legacy/veilend-backend/src/supabase/supabase.service.ts delete mode 100644 legacy/veilend-backend/src/transactions/transactions.controller.ts delete mode 100644 legacy/veilend-backend/src/transactions/transactions.module.ts delete mode 100644 legacy/veilend-backend/src/transactions/transactions.service.ts delete mode 100644 legacy/veilend-backend/src/users/users.controller.ts delete mode 100644 legacy/veilend-backend/src/users/users.module.ts delete mode 100644 legacy/veilend-backend/src/users/users.service.spec.ts delete mode 100644 legacy/veilend-backend/src/users/users.service.ts delete mode 100644 legacy/veilend-backend/supabase_schema.sql delete mode 100644 legacy/veilend-backend/test/app.e2e-spec.ts delete mode 100644 legacy/veilend-backend/test/jest-e2e.json delete mode 100644 legacy/veilend-backend/tsconfig.build.json delete mode 100644 legacy/veilend-backend/tsconfig.json delete mode 100644 veilend-backend/.env.example delete mode 100644 veilend-backend/.prettierrc delete mode 100644 veilend-backend/INDEXER.md delete mode 100644 veilend-backend/README.md delete mode 100644 veilend-backend/eslint.config.mjs delete mode 100644 veilend-backend/nest-cli.json delete mode 100644 veilend-backend/package-lock.json delete mode 100644 veilend-backend/package.json delete mode 100644 veilend-backend/prisma/schema.prisma delete mode 100644 veilend-backend/src/admin/admin.controller.ts delete mode 100644 veilend-backend/src/admin/admin.module.ts delete mode 100644 veilend-backend/src/admin/admin.service.ts delete mode 100644 veilend-backend/src/app.controller.spec.ts delete mode 100644 veilend-backend/src/app.controller.ts delete mode 100644 veilend-backend/src/app.module.ts delete mode 100644 veilend-backend/src/app.service.ts delete mode 100644 veilend-backend/src/assets/assets.controller.ts delete mode 100644 veilend-backend/src/assets/assets.module.ts delete mode 100644 veilend-backend/src/assets/assets.service.ts delete mode 100644 veilend-backend/src/auth/auth.controller.ts delete mode 100644 veilend-backend/src/auth/auth.module.ts delete mode 100644 veilend-backend/src/auth/auth.service.ts delete mode 100644 veilend-backend/src/auth/dto/nonce.dto.ts delete mode 100644 veilend-backend/src/auth/dto/verify-wallet.dto.ts delete mode 100644 veilend-backend/src/common/dto/api-response.dto.ts delete mode 100644 veilend-backend/src/common/dto/page-meta.dto.ts delete mode 100644 veilend-backend/src/common/dto/page-options.dto.ts delete mode 100644 veilend-backend/src/common/dto/page.dto.ts delete mode 100644 veilend-backend/src/events/events.entity.ts delete mode 100644 veilend-backend/src/indexer/indexer.config.ts delete mode 100644 veilend-backend/src/indexer/indexer.controller.ts delete mode 100644 veilend-backend/src/indexer/indexer.module.ts delete mode 100644 veilend-backend/src/indexer/indexer.repository.ts delete mode 100644 veilend-backend/src/indexer/indexer.service.spec.ts delete mode 100644 veilend-backend/src/indexer/indexer.service.ts delete mode 100644 veilend-backend/src/jobs/jobs.module.ts delete mode 100644 veilend-backend/src/jobs/processors/backfill.processor.ts delete mode 100644 veilend-backend/src/jobs/processors/event.processor.ts delete mode 100644 veilend-backend/src/jobs/queues/event.queue.ts delete mode 100644 veilend-backend/src/main.ts delete mode 100644 veilend-backend/src/portfolios/portfolios.controller.ts delete mode 100644 veilend-backend/src/portfolios/portfolios.module.ts delete mode 100644 veilend-backend/src/portfolios/portfolios.service.ts delete mode 100644 veilend-backend/src/stellar/horizon.service.spec.ts delete mode 100644 veilend-backend/src/stellar/horizon.service.ts delete mode 100644 veilend-backend/src/stellar/soroban-rpc.service.spec.ts delete mode 100644 veilend-backend/src/stellar/soroban-rpc.service.ts delete mode 100644 veilend-backend/src/stellar/stellar-account.service.spec.ts delete mode 100644 veilend-backend/src/stellar/stellar-account.service.ts delete mode 100644 veilend-backend/src/stellar/stellar.config.ts delete mode 100644 veilend-backend/src/stellar/stellar.module.ts delete mode 100644 veilend-backend/src/stellar/types.ts delete mode 100644 veilend-backend/src/transactions/transactions.controller.ts delete mode 100644 veilend-backend/src/transactions/transactions.module.ts delete mode 100644 veilend-backend/src/transactions/transactions.service.ts delete mode 100644 veilend-backend/src/wallet/wallet.module.ts delete mode 100644 veilend-backend/src/wallet/wallet.service.ts delete mode 100644 veilend-backend/test/app.e2e-spec.ts delete mode 100644 veilend-backend/test/jest-e2e.json delete mode 100644 veilend-backend/tsconfig.build.json delete mode 100644 veilend-backend/tsconfig.json delete mode 100644 veilend-mobile/.env delete mode 100644 veilend-mobile/.env.example delete mode 100644 veilend-mobile/.gitignore delete mode 100644 veilend-mobile/App.tsx delete mode 100644 veilend-mobile/app.json delete mode 100644 veilend-mobile/assets/adaptive-icon.png delete mode 100644 veilend-mobile/assets/favicon.png delete mode 100644 veilend-mobile/assets/icon.png delete mode 100644 veilend-mobile/assets/splash-icon.png delete mode 100644 veilend-mobile/babel.config.js delete mode 100644 veilend-mobile/eas.json delete mode 100644 veilend-mobile/index.js delete mode 100644 veilend-mobile/package-lock.json delete mode 100644 veilend-mobile/package.json delete mode 100644 veilend-mobile/postcss.config.js delete mode 100644 veilend-mobile/src/components/ErrorBoundary.tsx delete mode 100644 veilend-mobile/src/components/ProtocolStatusBanners.tsx delete mode 100644 veilend-mobile/src/data/mockData.ts delete mode 100644 veilend-mobile/src/hooks/useStellarAuth.ts delete mode 100644 veilend-mobile/src/navigation/index.tsx delete mode 100644 veilend-mobile/src/screens/BorrowScreen.tsx delete mode 100644 veilend-mobile/src/screens/ConnectWalletScreen.tsx delete mode 100644 veilend-mobile/src/screens/DashboardScreen.tsx delete mode 100644 veilend-mobile/src/screens/DepositScreen.tsx delete mode 100644 veilend-mobile/src/screens/RepayScreen.tsx delete mode 100644 veilend-mobile/src/store/store.test.ts delete mode 100644 veilend-mobile/src/store/store.ts delete mode 100644 veilend-mobile/src/types/expo-vector-icons.d.ts delete mode 100644 veilend-mobile/src/types/nativewind-env.d.ts delete mode 100644 veilend-mobile/src/types/zustand.d.ts delete mode 100644 veilend-mobile/src/utils/api.ts delete mode 100644 veilend-mobile/src/utils/errorReporting.test.ts delete mode 100644 veilend-mobile/src/utils/errorReporting.ts delete mode 100644 veilend-mobile/src/utils/helpers.ts delete mode 100644 veilend-mobile/src/utils/protocolStatus.test.ts delete mode 100644 veilend-mobile/src/utils/protocolStatus.ts delete mode 100644 veilend-mobile/src/utils/secureStoreShim.ts delete mode 100644 veilend-mobile/src/utils/toast.ts delete mode 100644 veilend-mobile/tailwind.config.js delete mode 100644 veilend-mobile/tsconfig.json delete mode 100644 veilend-soroban/.cargo/config.toml delete mode 100644 veilend-soroban/Cargo.lock delete mode 100644 veilend-soroban/Cargo.toml delete mode 100644 veilend-soroban/README.md delete mode 100644 veilend-soroban/rust-toolchain.toml delete mode 100644 veilend-soroban/src/lib.rs delete mode 100644 veilend-soroban/test_snapshots/test_borrow_exceeds_oracle_collateral_limit.1.json delete mode 100644 veilend-soroban/test_snapshots/test_borrow_with_oracle_price.1.json delete mode 100644 veilend-soroban/test_snapshots/test_configure_asset.1.json delete mode 100644 veilend-soroban/test_snapshots/test_get_oracle_price_not_set.1.json delete mode 100644 veilend-soroban/test_snapshots/test_initialize.1.json delete mode 100644 veilend-soroban/test_snapshots/test_min_collateral_ratio.1.json delete mode 100644 veilend-soroban/test_snapshots/test_oracle_price.1.json delete mode 100644 veilend-soroban/test_snapshots/test_oracle_price_default_to_one.1.json delete mode 100644 veilend-soroban/test_snapshots/test_set_oracle_price.1.json delete mode 100644 veilend-soroban/test_snapshots/test_set_oracle_price_invalid_price.1.json delete mode 100644 veilend-soroban/test_snapshots/test_set_oracle_price_unauthorized.1.json delete mode 100644 veilend-soroban/test_snapshots/test_withdraw_exceeds_oracle_collateral_limit.1.json delete mode 100644 veilend-soroban/veilend_hello/Cargo.toml delete mode 100644 veilend-soroban/veilend_hello/src/lib.rs delete mode 100644 veilend-soroban/veilend_hello/tests/test.rs delete mode 100644 veilend-web/.env.example delete mode 100644 veilend-web/.gitignore delete mode 100644 veilend-web/.prettierrc delete mode 100644 veilend-web/AGENTS.md delete mode 100644 veilend-web/CLAUDE.md delete mode 100644 veilend-web/README.md delete mode 100644 veilend-web/components.json delete mode 100644 veilend-web/eslint.config.mjs delete mode 100644 veilend-web/next.config.ts delete mode 100644 veilend-web/package-lock.json delete mode 100644 veilend-web/package.json delete mode 100644 veilend-web/postcss.config.mjs delete mode 100644 veilend-web/public/file.svg delete mode 100644 veilend-web/public/globe.svg delete mode 100644 veilend-web/public/next.svg delete mode 100644 veilend-web/public/vercel.svg delete mode 100644 veilend-web/public/window.svg delete mode 100644 veilend-web/src/app/(dashboard)/page.tsx delete mode 100644 veilend-web/src/app/api/campaign-events/route.ts delete mode 100644 veilend-web/src/app/dashboard/error.tsx delete mode 100644 veilend-web/src/app/dashboard/loading.tsx delete mode 100644 veilend-web/src/app/dashboard/page.tsx delete mode 100644 veilend-web/src/app/favicon.ico delete mode 100644 veilend-web/src/app/globals.css delete mode 100644 veilend-web/src/app/layout.tsx delete mode 100644 veilend-web/src/app/page.tsx delete mode 100644 veilend-web/src/components/AmountInput.tsx delete mode 100644 veilend-web/src/components/CampaignTracker.tsx delete mode 100644 veilend-web/src/components/ContributorInterest.tsx delete mode 100644 veilend-web/src/components/Layout.tsx delete mode 100644 veilend-web/src/components/SyncStatusBadge.tsx delete mode 100644 veilend-web/src/components/TrackedLink.tsx delete mode 100644 veilend-web/src/components/WalletConnect.tsx delete mode 100644 veilend-web/src/components/WalletStatus.tsx delete mode 100644 veilend-web/src/components/ui/alert.tsx delete mode 100644 veilend-web/src/components/ui/badge.tsx delete mode 100644 veilend-web/src/components/ui/button.tsx delete mode 100644 veilend-web/src/components/ui/card.tsx delete mode 100644 veilend-web/src/components/ui/checkbox.tsx delete mode 100644 veilend-web/src/components/ui/dialog.tsx delete mode 100644 veilend-web/src/components/ui/input.tsx delete mode 100644 veilend-web/src/components/ui/progress.tsx delete mode 100644 veilend-web/src/components/ui/separator.tsx delete mode 100644 veilend-web/src/components/ui/skeleton.tsx delete mode 100644 veilend-web/src/context/WalletContext.tsx delete mode 100644 veilend-web/src/hooks/useStellarWallet.ts delete mode 100644 veilend-web/src/lib/api/dashboard.ts delete mode 100644 veilend-web/src/lib/campaignAnalytics.ts delete mode 100644 veilend-web/src/lib/config-validation.ts delete mode 100644 veilend-web/src/lib/hooks/usePositionSync.ts delete mode 100644 veilend-web/src/lib/stellar/auth.ts delete mode 100644 veilend-web/src/lib/stellar/config.ts delete mode 100644 veilend-web/src/lib/stellar/wallet.ts delete mode 100644 veilend-web/src/lib/types/dashboard.ts delete mode 100644 veilend-web/src/lib/utils.ts delete mode 100644 veilend-web/src/lib/validation/amount.test.ts delete mode 100644 veilend-web/src/lib/validation/amount.ts delete mode 100644 veilend-web/tsconfig.json diff --git a/.github/workflows/mobile-ci.yml b/.github/workflows/mobile-ci.yml deleted file mode 100644 index 72d20a4..0000000 --- a/.github/workflows/mobile-ci.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Mobile CI - -on: - push: - branches: - - main - paths: - - "veilend-mobile/**" - - ".github/workflows/mobile-ci.yml" - pull_request: - types: - - opened - - synchronize - - reopened - - ready_for_review - paths: - - "veilend-mobile/**" - - ".github/workflows/mobile-ci.yml" - workflow_dispatch: - -concurrency: - group: mobile-ci-${{ github.ref }} - cancel-in-progress: true - -jobs: - mobile-checks: - runs-on: ubuntu-latest - defaults: - run: - working-directory: veilend-mobile - - env: - CI: "1" - NPM_CONFIG_LEGACY_PEER_DEPS: "true" - - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: npm - cache-dependency-path: veilend-mobile/package-lock.json - - - name: Install dependencies - run: npm ci --legacy-peer-deps - - - name: Type check - run: npx tsc --noEmit - - - name: Validate Expo configuration - run: npx expo config --type public > /dev/null - - - name: Run Expo Doctor - run: npx expo-doctor@latest diff --git a/.github/workflows/soroban-ci.yml b/.github/workflows/soroban-ci.yml deleted file mode 100644 index 480ee7c..0000000 --- a/.github/workflows/soroban-ci.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Soroban CI - -on: - push: - branches: - - main - paths: - - "veilend-soroban/**" - - ".github/workflows/soroban-ci.yml" - pull_request: - types: - - opened - - synchronize - - reopened - - ready_for_review - paths: - - "veilend-soroban/**" - - ".github/workflows/soroban-ci.yml" - workflow_dispatch: - -concurrency: - group: soroban-ci-${{ github.ref }} - cancel-in-progress: true - -jobs: - soroban-checks: - runs-on: ubuntu-latest - defaults: - run: - working-directory: veilend-soroban - - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up Rust toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: 1.88.0 - components: rustfmt, clippy - targets: wasm32-unknown-unknown, wasm32v1-none - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 - with: - workspaces: | - veilend-soroban -> target - - - name: Check formatting - run: cargo fmt --all -- --check - - - name: Run Clippy - run: cargo clippy --locked --all-targets -- -D warnings - - - name: Run tests - run: cargo test --locked --target x86_64-unknown-linux-gnu - - - name: Build release wasm - run: cargo build --locked --target wasm32-unknown-unknown --release - - - name: Install Linux dependencies for Stellar CLI - run: | - sudo apt-get update - sudo apt-get install -y pkg-config libdbus-1-dev libudev-dev - - - name: Install Stellar CLI - run: cargo install --locked stellar-cli --version 23.0.1 - - - name: Build Soroban contract artifact - run: stellar contract build diff --git a/.github/workflows/veilend-backend.yml b/.github/workflows/veilend-backend.yml deleted file mode 100644 index 9a457ae..0000000 --- a/.github/workflows/veilend-backend.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: VeilLend Backend CI - -on: - push: - paths: - - 'veilend-backend/**' - pull_request: - paths: - - 'veilend-backend/**' - -jobs: - build-and-test: - runs-on: ubuntu-latest - - defaults: - run: - working-directory: veilend-backend - - strategy: - matrix: - node-version: [20.x] - - steps: - - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - cache-dependency-path: 'veilend-backend/package-lock.json' - - - name: Install dependencies - run: npm ci - - - name: Lint - run: npm run lint - - - name: Build - run: npm run build - - - name: Test - run: npm run test diff --git a/.github/workflows/web-ci.yml b/.github/workflows/web-ci.yml index cf50c02..e69de29 100644 --- a/.github/workflows/web-ci.yml +++ b/.github/workflows/web-ci.yml @@ -1,53 +0,0 @@ -name: Web CI - -on: - push: - branches: - - main - paths: - - "veilend-web/**" - - ".github/workflows/web-ci.yml" - pull_request: - types: - - opened - - synchronize - - reopened - - ready_for_review - paths: - - "veilend-web/**" - - ".github/workflows/web-ci.yml" - workflow_dispatch: - -concurrency: - group: web-ci-${{ github.ref }} - cancel-in-progress: true - -jobs: - web-checks: - runs-on: ubuntu-latest - defaults: - run: - working-directory: veilend-web - - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: npm - cache-dependency-path: veilend-web/package-lock.json - - - name: Install dependencies - run: npm ci - - - name: Type check - run: npm run type-check - - - name: Lint - run: npm run lint - - - name: Build - run: npm run build diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d837074..0000000 --- a/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# Rust build artifacts -/target/ -/veilend-soroban/target/ - -# Root planning backlogs -/backend.md -/mobile.md -/soroban.md -/web.md - -# Node.js -node_modules/ -dist/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.env diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index e6e5ef6..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1864 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" -dependencies = [ - "derive_arbitrary", -] - -[[package]] -name = "ark-bls12-381" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", -] - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", - "itertools", - "num-traits", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", - "derivative", - "digest", - "itertools", - "num-bigint", - "num-traits", - "paste", - "rustc_version", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-poly" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-serialize-derive", - "ark-std", - "digest", - "num-bigint", -] - -[[package]] -name = "ark-serialize-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bs58" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "bumpalo" -version = "3.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes-lit" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0adabf37211a5276e46335feabcbb1530c95eb3fdf85f324c7db942770aa025d" -dependencies = [ - "num-bigint", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "cc" -version = "1.2.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_eval" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "chrono" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" -dependencies = [ - "iana-time-zone", - "num-traits", - "serde", - "windows-link", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crate-git-revision" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98" -dependencies = [ - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "ctor" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb" -dependencies = [ - "ctor-proc-macro", - "dtor", -] - -[[package]] -name = "ctor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core 0.23.0", - "darling_macro 0.23.0", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core 0.23.0", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "data-encoding" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "serde_core", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_arbitrary" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dtor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core", - "serde", - "sha2", - "subtle", - "zeroize", -] - -[[package]] -name = "either" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "escape-bytes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bfcf67fea2815c2fc3b90873fae90957be12ff417335dfadc7f52927feb03b2" - -[[package]] -name = "ethnum" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40404c3f5f511ec4da6fe866ddf6a717c309fdbb69fbbad7b0f3edab8f2e835f" - -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.1", - "serde", - "serde_core", -] - -[[package]] -name = "indexmap-nostd" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "js-sys" -version = "0.3.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" -dependencies = [ - "cfg-if", - "futures-util", - "wasm-bindgen", -] - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sha2", -] - -[[package]] -name = "keccak" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "log" -version = "0.4.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" - -[[package]] -name = "macro-string" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "memchr" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "schemars" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "dyn-clone", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "subtle", - "zeroize", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_json" -version = "1.0.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_with" -version = "3.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" -dependencies = [ - "base64", - "bs58", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.14.0", - "schemars 0.8.22", - "schemars 0.9.0", - "schemars 1.2.1", - "serde_core", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" -dependencies = [ - "darling 0.23.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha3" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" -dependencies = [ - "digest", - "keccak", -] - -[[package]] -name = "shlex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core", -] - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" - -[[package]] -name = "soroban-builtin-sdk-macros" -version = "23.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9336adeabcd6f636a4e0889c8baf494658ef5a3c4e7e227569acd2ce9091e85" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "soroban-env-common" -version = "23.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00067f52e8bbf1abf0de03fe3e2fbb06910893cfbe9a7d9093d6425658833ff3" -dependencies = [ - "arbitrary", - "crate-git-revision", - "ethnum", - "num-derive", - "num-traits", - "serde", - "soroban-env-macros", - "soroban-wasmi", - "static_assertions", - "stellar-xdr", - "wasmparser", -] - -[[package]] -name = "soroban-env-guest" -version = "23.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd1e40963517b10963a8e404348d3fe6caf9c278ac47a6effd48771297374d6" -dependencies = [ - "soroban-env-common", - "static_assertions", -] - -[[package]] -name = "soroban-env-host" -version = "23.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9766c5ad78e9d8ae10afbc076301f7d610c16407a1ebb230766dbe007a48725" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-serialize", - "curve25519-dalek", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", - "generic-array", - "getrandom", - "hex-literal", - "hmac", - "k256", - "num-derive", - "num-integer", - "num-traits", - "p256", - "rand", - "rand_chacha", - "sec1", - "sha2", - "sha3", - "soroban-builtin-sdk-macros", - "soroban-env-common", - "soroban-wasmi", - "static_assertions", - "stellar-strkey 0.0.13", - "wasmparser", -] - -[[package]] -name = "soroban-env-macros" -version = "23.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e6a1c5844257ce96f5f54ef976035d5bd0ee6edefaf9f5e0bcb8ea4b34228c" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "serde", - "serde_json", - "stellar-xdr", - "syn 2.0.117", -] - -[[package]] -name = "soroban-ledger-snapshot" -version = "23.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea7299402f5f445089fde192cc68587baf0cc6432be300bce99d997fd85b4cb" -dependencies = [ - "serde", - "serde_json", - "serde_with", - "soroban-env-common", - "soroban-env-host", - "thiserror", -] - -[[package]] -name = "soroban-sdk" -version = "23.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1e11f9fd537f9df29ec1a66c1b78d666094df56e196565d292ebf9a72732b4" -dependencies = [ - "arbitrary", - "bytes-lit", - "crate-git-revision", - "ctor", - "derive_arbitrary", - "ed25519-dalek", - "rand", - "rustc_version", - "serde", - "serde_json", - "soroban-env-guest", - "soroban-env-host", - "soroban-ledger-snapshot", - "soroban-sdk-macros", - "stellar-strkey 0.0.16", - "visibility", -] - -[[package]] -name = "soroban-sdk-macros" -version = "23.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa7114e2f031b6fbd30376e844f3c55f6daf56f6f9d33ce309f846ffced316d" -dependencies = [ - "darling 0.20.11", - "heck", - "itertools", - "macro-string", - "proc-macro2", - "quote", - "sha2", - "soroban-env-common", - "soroban-spec", - "soroban-spec-rust", - "stellar-xdr", - "syn 2.0.117", -] - -[[package]] -name = "soroban-spec" -version = "23.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1303589e67e7c76d0571b8d797b75f9fa33a1ceb1b4361a981570a3ebf00ac19" -dependencies = [ - "base64", - "stellar-xdr", - "thiserror", - "wasmparser", -] - -[[package]] -name = "soroban-spec-rust" -version = "23.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956188f28b750b80a2bb4cd5698038746edae1be51ec19a29c7efc6dcd922e5f" -dependencies = [ - "prettyplease", - "proc-macro2", - "quote", - "sha2", - "soroban-spec", - "stellar-xdr", - "syn 2.0.117", - "thiserror", -] - -[[package]] -name = "soroban-wasmi" -version = "0.31.1-soroban.20.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719" -dependencies = [ - "smallvec", - "spin", - "wasmi_arena", - "wasmi_core", - "wasmparser-nostd", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stellar-strkey" -version = "0.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1832fb50c651ad10f734aaf5d31ca5acdfb197a6ecda64d93fcdb8885af913" -dependencies = [ - "crate-git-revision", - "data-encoding", -] - -[[package]] -name = "stellar-strkey" -version = "0.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084afcb0d458c3d5d5baa2d294b18f881e62cc258ef539d8fdf68be7dbe45520" -dependencies = [ - "crate-git-revision", - "data-encoding", - "heapless", -] - -[[package]] -name = "stellar-xdr" -version = "23.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d2848e1694b0c8db81fd812bfab5ea71ee28073e09ccc45620ef3cf7a75a9b" -dependencies = [ - "arbitrary", - "base64", - "cfg_eval", - "crate-git-revision", - "escape-bytes", - "ethnum", - "hex", - "serde", - "serde_with", - "sha2", - "stellar-strkey 0.0.13", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "time" -version = "0.3.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" - -[[package]] -name = "time-macros" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "typenum" -version = "1.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "veillend-contract" -version = "0.1.0" -dependencies = [ - "soroban-sdk", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "visibility" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasm-bindgen" -version = "0.2.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn 2.0.117", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasmi_arena" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" - -[[package]] -name = "wasmi_core" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" -dependencies = [ - "downcast-rs", - "libm", - "num-traits", - "paste", -] - -[[package]] -name = "wasmparser" -version = "0.116.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" -dependencies = [ - "indexmap 2.14.0", - "semver", -] - -[[package]] -name = "wasmparser-nostd" -version = "0.100.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" -dependencies = [ - "indexmap-nostd", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "zerocopy" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zeroize" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 7b11edf..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[workspace] -members = ["veilend-soroban"] -exclude = ["veilend-soroban/veilend_hello"] -resolver = "2" - -[profile.release] -opt-level = "z" -overflow-checks = true -debug = 0 -strip = "symbols" -debug-assertions = false -panic = "abort" -codegen-units = 1 -lto = true - -[profile.release-with-logs] -inherits = "release" -debug-assertions = true diff --git a/README.md b/README.md deleted file mode 100644 index f3e6658..0000000 --- a/README.md +++ /dev/null @@ -1,223 +0,0 @@ -# 🛡️ VeilLend - -> **Private Lending. Stellar Speed. X-Ray Privacy.** - -**VeilLend** is a privacy-first decentralized lending protocol built on **Stellar/Soroban**, enabling users to deposit, borrow, and transact with complete financial privacy—powered by **X-Ray ZK proofs** for shielded transactions . With sub-second settlements, near-zero fees (<0.01¢), and multi-chain support, VeilLend is designed for instant, borderless DeFi. - -This tool is ideal for: -- 💼 Freelancers managing cross-border payments and lending -- 🎨 Creators accepting private donations and loans -- 🌍 Individuals handling remittances with financial privacy -- 🏢 Small businesses streamlining asset management across blockchains - -Whether you're a solo developer building privacy-first finance or a team scaling multi-chain DeFi, VeilLend prioritises simplicity, self-custody, and security without intermediaries. - ---- - -## 🏗️ Architecture - -VeilLend is currently organized around the active Stellar contract and mobile app workspaces, with older implementation work archived under `legacy/` for reference: - -``` -veillend/ -├── veilend-soroban/ # Active Soroban Rust contract workspace for VeilLend on Stellar -├── veilend-mobile/ # Active React Native / Expo mobile app -├── veilend-web/ # Active Next.js 16 web application -├── legacy/ -│ ├── veilend-backend/ # Archived NestJS backend from the previous architecture -│ └── docs/ # Archived migration notes and contributor docs -└── README.md -``` - -| Component | Tech Stack | Description | -| :--- | :--- | :--- | -| **Smart Contracts** | **Rust/Soroban** | Initial VeilLend contract scaffold for lending state, asset configuration, and event emission on Stellar. | -| **Mobile App** | **React Native (Expo)** | Cross-platform mobile experience for deposit, borrow, repay, privacy mode, and wallet-driven onboarding. | -| **Web App** | **Next.js 16 / TypeScript** | Privacy-first web interface for VeilLend on Stellar, with App Router, Tailwind CSS, and full TypeScript support. | -| **Backend API** | **Planned Rebuild** | The backend is being rebuilt for the Stellar ecosystem; the previous NestJS version is archived in `legacy/veilend-backend`. | -| **Archived Research** | **Markdown / Notes** | Migration notes and previous contributor docs are preserved in `legacy/docs`. | - ---- - -## 🔐 Smart Contracts (Soroban/Rust) - -Located in `/veilend-soroban`, the current Soroban codebase is the new VeilLend contract foundation on Stellar. - -### Current contract foundation -- Initializes the contract with an admin and minimum collateral ratio. -- Tracks supported assets for lending actions. -- Stores per-user positions with deposited and borrowed balances. -- Exposes basic `deposit`, `borrow`, `repay`, and `withdraw` state transitions. -- Emits events for indexing and analytics. -- **Oracle-backed collateral valuation** using configurable asset prices for accurate borrowing power calculations. - -### Planned next layer -- Stellar token transfer integration for real asset movement. -- Liquidation rules based on oracle price thresholds. -- Shielded commitment/nullifier flows for privacy-preserving actions. -- Additional testing, security review, and deployment automation. - ---- - -## ⚠️ Error Reference - -All contract errors are typed via `VeilLendError` (`#[contracterror]`, `#[repr(u32)]`). Each variant maps to a unique `u32` code that client integrators can match on. - -| Variant | Code | When it fires | -|---------|------|---------------| -| `AlreadyInitialized` | 1 | `__constructor` called when admin is already set | -| `Unauthorized` | 2 | Non-admin caller on admin-only functions (`configure_asset`, `set_oracle_price`) | -| `UnsupportedAsset` | 3 | Operation on an asset not yet configured via `configure_asset` | -| `InvalidAmount` | 4 | Negative amount passed to `deposit`, `borrow`, `repay`, `withdraw` | -| `InsufficientCollateral` | 5 | `borrow` or `withdraw` would push collateral ratio below minimum | -| `InsufficientDeposit` | 6 | `withdraw` amount exceeds user's deposited balance | -| `RepayTooLarge` | 7 | `repay` amount exceeds user's outstanding borrowed balance | -| `InvalidCollateralRatio` | 8 | `__constructor` called with `min_collateral_ratio_bps < 10_000` (< 100%) | -| `NotInitialized` | 9 | Any function requiring admin called before `__constructor` | -| `ZeroAmount` | 10 | Zero amount passed to `deposit`, `borrow`, `repay`, `withdraw` | -| `OraclePriceMissing` | 11 | `borrow` or `withdraw` on an asset without a configured oracle price | -| `ContractPaused` | 12 | Any state-changing function called while contract is paused | - -### Error handling notes -- Zero and negative amounts produce **different** errors (`ZeroAmount` vs `InvalidAmount`) so clients can distinguish them. -- Oracle price missing is a **hard error** (not a silent default) — borrow/withdraw will fail explicitly if no price is set. -- `NotInitialized` and `Unauthorized` are distinct: the first means "contract not set up yet", the second means "you are not the admin". - ---- - -## 📱 Mobile App Features - -### Core -- **🛡️ X-Ray Privacy Dashboard**: Toggle "Privacy Mode" to mask balances and positions with zero-knowledge proofs. -- **🔑 Wallet Login**: Authenticate securely using cryptographic signatures and wallet-based onboarding. -- **Protocol Status Banners**: Surface wallet disconnects, Stellar network mismatches, and stale protocol sync state with clear recovery actions. -- **⚡ Instant Actions**: One-tap Deposit, Borrow, and Repay flows across multiple blockchains. -- **🔄 Rebuild-Friendly Architecture**: The app is being prepared for a new Stellar-native backend and contributor-driven implementation. - -### Privacy & Security -- **X-Ray Privacy Toggle**: Designed to hide sensitive balances and activity as the privacy layer is integrated. -- **Scam Alerts**: Flags suspicious transactions (e.g., unusual patterns, missing memos). -- **Self-Custody**: Funds route directly to your wallet—no central holding. - -### Advanced (v2+) -- **Multi-asset support** with future expansion across Stellar-native and interoperable assets. -- **Recurring loan/repayment links** for automated financial management. -- **Fiat on/off-ramps** (MoneyGram, Banxa) for seamless fiat-to-crypto conversion. -- **Notifications** (email/Telegram) for transaction confirmations and alerts. - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Node.js** (v18+; nodejs.org) -- **Rust toolchain** (for Soroban contracts; install via rustup.rs) -- **Stellar CLI** (for contract deployment; on Ubuntu install `pkg-config`, `libdbus-1-dev`, and `libudev-dev` first, then run `cargo install --locked stellar-cli --version 23.0.1`) -- **Docker** (for local Stellar network; docker.com) -- **A Stellar wallet** (Freighter recommended; freighter.app) -- **Git** (for cloning) -- **Expo Go** (for mobile testing) - -### Installation -Clone the repository: - -```bash -git clone https://github.com/your-org/veillend.git -cd veillend - -# Install mobile dependencies -cd veilend-mobile && npm install -``` - -### Environment Setup -Configure the Stellar network: -- **Development**: Defaults to testnet; fund your wallet at laboratory.stellar.org -- **Production**: Ensure your wallet holds the required live assets and network configuration - -For contracts: Add environment variables in the `veilend-soroban/` workspace as needed for your target Stellar network and deployment flow. - -### Running Locally -Start the mobile app from its workspace: - -```bash -cd veilend-mobile && npm install && npx expo start -``` - -For contracts (testing/deploying): -```bash -cd veilend-soroban -cargo build --target wasm32-unknown-unknown --release -stellar contract build -``` - -The previous backend and migration documents remain available under `legacy/` while the new Stellar-native backend is rebuilt. - ---- - -## 🛠️ Tech Deep Dive: ZK Privacy Flow (Stellar) - -1. **Client-Side**: User selects a privacy-enabled lending action from the mobile app. -2. **Preparation**: The app prepares lending inputs and any privacy metadata needed for the action. -3. **On-Chain**: The Soroban contract records the position update and emits events for indexing. -4. **Off-Chain Services**: A new Stellar-native backend will eventually sync positions and transaction history for the app experience. -5. **Future Privacy Layer**: Shielded commitments and proof verification will extend this flow in later releases. - ---- - -## 📜 License -MIT - -## 🌟 Join the Drips Monthly Wave Contributor Program - -We're actively seeking contributors to help build VeilLend on Stellar! This is your opportunity to: - -- ✨ Contribute to cutting-edge privacy-focused DeFi on Stellar -- 💰 Earn rewards through the Drips contributor program -- 🤝 Collaborate with experienced blockchain developers -- 🚀 Gain experience with Soroban, Rust, and multi-chain development - -### How to Get Started: -1. **Setup**: Follow the Getting Started guide above -2. **Pick an Issue**: Check GitHub issues labeled `good-first-issue`, `soroban`, `mobile`, or `privacy` -3. **Contribute**: Implement features, fix bugs, or help shape the new Stellar-native backend -4. **Submit**: Create a PR with tests and documentation updates - -### Testing -Run tests to validate code quality and functionality: - -```bash -# Soroban contract checks -cd veilend-soroban && cargo build --locked --target wasm32-unknown-unknown --release - -# Mobile-specific tests -cd veilend-mobile && npm test -``` - -### Deployment -Deployment is automated for most components: - -- **Mobile**: Use Expo CLI for over-the-air updates or app store builds -- **Contracts**: Build and deploy from the `veilend-soroban/` workspace using Cargo and Stellar CLI -- **Backend**: The new Stellar-native backend will be introduced after the archived implementation is replaced - -### Contributing -Contributions are welcome and encouraged to help evolve VeilLend! To get started: - -- **Report Issues**: Use GitHub Issues for bugs or feature requests. Include reproduction steps, environment details, and screenshots where possible. -- **Propose Features**: Start a Discussion thread to align on ideas before coding. -- **Submit Pull Requests**: - - Fork the repository and create a feature branch: `git checkout -b feature/your-feature` - - Implement changes, ensuring they pass linting and tests - - Commit with clear messages (e.g., "feat: add multi-asset swap support") - - Push and open a PR against `main`. Reference any related issues. - -All contributors must adhere to the Code of Conduct and sign off commits for DCO compliance. - -### Resources: -- [Soroban Documentation](https://soroban.stellar.org/docs) -- [Stellar Developer Docs](https://developers.stellar.org/docs) -- Archived research: `legacy/docs` -- [Drips Contributor Program](https://drips.network/contributors) -- [Stellar Discord](https://discord.gg/stellardev) - -**Ready to contribute?** Start with the VeilLend Soroban contract in `/veilend-soroban` and help us build the future of private lending on Stellar! 🌟 diff --git a/legacy/README.md b/legacy/README.md deleted file mode 100644 index 0c0c28e..0000000 --- a/legacy/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Legacy Archive - -This folder contains archived VeilLend work from the previous architecture. - -### Archived Workspaces - -- `veilend-backend/`: the earlier NestJS backend implementation -- `docs/`: migration notes, research documents, and older contributor guidance - -### Purpose - -These files are kept for historical reference only while the project is rebuilt around the Stellar ecosystem. - -Contributors should treat `veilend-mobile/` and `veilend-soroban/` as the active workspaces unless a task explicitly points into `legacy/`. diff --git a/legacy/docs/CONTRIBUTING_SOROBAN.md b/legacy/docs/CONTRIBUTING_SOROBAN.md deleted file mode 100644 index 6478ae9..0000000 --- a/legacy/docs/CONTRIBUTING_SOROBAN.md +++ /dev/null @@ -1,1086 +0,0 @@ -# VeilLend: Soroban Developer Onboarding Guide - -> **Step-by-step guide for setting up your local Soroban development environment** - -**Last Updated:** May 2026 -**Difficulty:** Beginner to Intermediate -**Estimated Setup Time:** 30-45 minutes - ---- - -## Table of Contents - -1. [Overview](#overview) -2. [Prerequisites](#prerequisites) -3. [Installation Guide](#installation-guide) - - [Step 1: Install Rust](#step-1-install-rust) - - [Step 2: Install Soroban CLI](#step-2-install-soroban-cli) - - [Step 3: Install Docker (Local Network)](#step-3-install-docker-local-network) - - [Step 4: Verify Installation](#step-4-verify-installation) -4. [Hello World: VeilLend Project Structure](#hello-world-veillend-project-structure) -5. [Essential VS Code Extensions](#essential-vs-code-extensions) -6. [Development Tools & Workflow](#development-tools--workflow) -7. [Quick Start: Build & Test](#quick-start-build--test) -8. [Common Issues & Troubleshooting](#common-issues--troubleshooting) -9. [Next Steps](#next-steps) -10. [Additional Resources](#additional-resources) - ---- - -## Overview - -This guide helps new contributors set up a complete Soroban development environment for the VeilLend project. VeilLend is a privacy-first decentralized lending protocol that currently runs on Starknet and is expanding to Stellar/Soroban. - -### What is Soroban? - -**Soroban** is Stellar's smart contract platform that allows developers to write decentralized applications using **Rust**. Key features: - -- ✅ **Rust-based**: Write smart contracts in a memory-safe, high-performance language -- ✅ **WASM compilation**: Contracts compile to WebAssembly for efficient execution -- ✅ **Cross-platform**: Deploy on Stellar testnet, mainnet, or local sandbox -- ✅ **Rich tooling**: CLI tools, local network, and testing frameworks - -### VeilLend Architecture (Stellar) - -VeilLend on Stellar will implement: - -| Component | Description | Status | -| --------------------- | ----------------------------------------------------- | ---------- | -| **LendingPool** | Core lending logic (deposit, borrow, repay, withdraw) | 📋 Planned | -| **ShieldedPool** | Privacy-preserving transactions with ZK proofs | 📋 Planned | -| **PriceOracle** | Asset price feeds with staleness detection | 📋 Planned | -| **ReserveData** | Reserve configuration and state management | 📋 Planned | -| **InterestToken** | Interest-bearing tokens (aTokens) | 📋 Planned | -| **AddressesProvider** | Central registry for all contracts | 📋 Planned | - -**📖 Migration Reference:** See `docs/migration/contract-mapping.md` for detailed Starknet → Soroban migration patterns. - ---- - -## ✅ Prerequisites - -Before starting, ensure you have: - -- **Operating System:** macOS, Linux, or Windows (WSL2 recommended) -- **Disk Space:** At least 5 GB free (Rust toolchain + Docker images) -- **Internet Connection:** Required for downloading dependencies -- **Terminal Access:** Basic command-line knowledge -- **Git:** Version control system - ---- - -## 🛠️ Installation Guide - -### Step 1: Install Rust - -Soroban contracts are written in Rust. We'll install the Rust toolchain using `rustup`. - -#### macOS / Linux - -```bash -# Install Rust using rustup -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - -# Follow the prompts (choose option 1 for default installation) - -# Load Rust environment into current shell -source $HOME/.cargo/env - -# Verify installation -rustc --version -cargo --version -``` - -#### Windows - -1. Download the installer from https://rustup.rs -2. Run the installer and follow the prompts -3. Open a new terminal and verify: - -```bash -rustc --version -cargo --version -``` - -#### Configure Rust for Soroban - -```bash -# Install the wasm32-unknown-unknown target (required for WASM compilation) -rustup target add wasm32-unknown-unknown - -# Update to latest stable version -rustup update stable -``` - -**Expected Output:** - -``` -rustc 1.76.0 (or higher) -cargo 1.76.0 (or higher) -``` - ---- - -### Step 2: Install Soroban CLI - -The Soroban CLI (`soroban`) is the primary tool for building, deploying, and interacting with contracts. - -#### Option A: Install via Cargo (Recommended) - -```bash -# Install the latest stable version -cargo install --locked soroban-cli - -# Verify installation -soroban --version -``` - -#### Option B: Install via Homebrew (macOS) - -```bash -# Add Stellar tap -brew tap stellar/tap - -# Install Soroban CLI -brew install soroban-cli - -# Verify installation -soroban --version -``` - -#### Option C: Install from Source - -```bash -# Clone the repository -git clone https://github.com/stellar/stellar-cli.git -cd stellar-cli - -# Build and install -cargo install --locked --path . - -# Verify installation -soroban --version -``` - -**Expected Output:** - -``` -soroban 21.0.0 (or higher) -``` - -#### Configure Soroban CLI - -```bash -# Add Stellar testnet network -soroban network add \ - testnet \ - --rpc-url https://soroban-testnet.stellar.org \ - --network-passphrase "Test SDF Network ; September 2015" - -# Add Stellar mainnet network -soroban network add \ - public \ - --rpc-url https://soroban-mainnet.stellar.org \ - --network-passphrase "Public Global Stellar Network ; September 2015" - -# Create a test account (for development) -soroban keys generate alice --network testnet - -# Fund the account with testnet lumens (XLM) -soroban keys fund alice --network testnet - -# Check account balance -soroban keys balance alice --network testnet -``` - ---- - -### Step 3: Install Docker (Local Network) - -Docker enables you to run a local Stellar network for fast, offline development and testing. - -#### macOS - -```bash -# Install Docker Desktop -brew install --cask docker - -# Start Docker Desktop from Applications -open -a Docker - -# Verify installation -docker --version -docker compose version -``` - -#### Linux (Ubuntu/Debian) - -```bash -# Install Docker Engine -curl -fsSL https://get.docker.com | sh - -# Add your user to the docker group (avoid using sudo) -sudo usermod -aG docker $USER - -# Apply group changes (or log out and back in) -newgrp docker - -# Start Docker service -sudo systemctl enable docker -sudo systemctl start docker - -# Verify installation -docker --version -docker compose version -``` - -#### Windows - -1. Download Docker Desktop from https://www.docker.com/products/docker-desktop -2. Run the installer and follow the prompts -3. Enable WSL2 backend during installation -4. Restart your computer -5. Verify: - -```bash -docker --version -docker compose version -``` - -#### Run Local Stellar Network - -```bash -# Pull the Stellar quickstart image (first time only, ~2GB) -docker pull stellar/quickstart:testing - -# Start local network -docker run --rm -it \ - -p 8000:8000 \ - -p 5432:5432 \ - stellar/quickstart:testing \ - --standalone \ - --enable-soroban-rpc - -# The network is ready when you see: -# "soroban rpc: listening on port 8000" -``` - -**Network Endpoints:** - -- **RPC URL:** `http://localhost:8000/soroban/rpc` -- **Horizon URL:** `http://localhost:8000` -- **Network Passphrase:** `Standalone Network ; February 2017` - -#### Configure Soroban for Local Network - -```bash -# Add local network to Soroban CLI -soroban network add \ - local \ - --rpc-url http://localhost:8000/soroban/rpc \ - --network-passphrase "Standalone Network ; February 2017" - -# Generate a local account -soroban keys generate bob --network local - -# Fund the account (local network has unlimited XLM) -soroban keys fund bob --network local - -# Check balance -soroban keys balance bob --network local -``` - ---- - -### Step 4: Verify Installation - -Run this comprehensive check to ensure everything is working: - -```bash -# Create a verification script -cat << 'EOF' > verify_setup.sh -#!/bin/bash - -echo "🔍 Verifying Soroban Development Environment..." -echo "" - -# Check Rust -echo "✓ Rust Toolchain:" -rustc --version -cargo --version -rustup target list --installed | grep wasm32 -echo "" - -# Check Soroban CLI -echo "✓ Soroban CLI:" -soroban --version -echo "" - -# Check Docker -echo "✓ Docker:" -docker --version -docker compose version -echo "" - -# Check local network -echo "✓ Local Network Connection:" -soroban network ls -echo "" - -# Check test account -echo "✓ Test Account Balance:" -soroban keys balance alice --network testnet 2>/dev/null || echo " Account not funded yet. Run: soroban keys fund alice --network testnet" -echo "" - -echo "✅ Setup verification complete!" -EOF - -chmod +x verify_setup.sh -./verify_setup.sh -``` - ---- - -## 👋 Hello World: VeilLend Project Structure - -Let's create a simple Soroban contract following VeilLend's project structure. - -### 1. Navigate to Contracts Directory - -```bash -cd /path/to/veillend - -# Create Soroban contracts directory (if it doesn't exist) -mkdir -p veilend-soroban -cd veilend-soroban -``` - -### 2. Initialize a New Soroban Project - -```bash -# Create a new contract using the official template -soroban contract init veilend_hello -cd veilend_hello -``` - -**Project Structure:** - -``` -veilend_hello/ -├── Cargo.toml # Rust dependencies -├── src/ -│ ├── lib.rs # Contract entry point -│ └── main.rs # Test harness -└── tests/ - └── test.rs # Integration tests -``` - -### 3. Understand the Contract Structure - -Let's examine the generated files: - -#### `Cargo.toml` - -```toml -[package] -name = "veilend_hello" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib"] -doctest = false - -[dependencies] -soroban-sdk = { version = "21.0.0" } - -[dev-dependencies] -soroban-sdk = { version = "21.0.0", features = ["testutils"] } -``` - -#### `src/lib.rs` - -```rust -use soroban_sdk::{contract, contractimpl, contractclient, symbol_short, Env, Symbol, Address}; - -#[contract] -pub struct VeilLendHelloContract; - -#[contractimpl] -impl VeilLendHelloContract { - /// Initialize the contract with an admin address - pub fn initialize(env: Env, admin: Address) { - admin.require_auth(); - env.storage().instance().set(&symbol_short!("admin"), &admin); - } - - /// Get the admin address - pub fn get_admin(env: Env) -> Address { - env.storage() - .instance() - .get(&symbol_short!("admin")) - .expect("Contract not initialized") - } - - /// Simple hello function - pub fn hello(env: Env, user: Address) -> Symbol { - user.require_auth(); - symbol_short!("Hello!") - } -} - -// Generate a client for testing -#[contractclient(name = "VeilLendHelloClient")] -impl VeilLendHelloContract; -``` - -### 4. Write Tests - -#### `tests/test.rs` - -```rust -#![cfg(test)] - -use soroban_sdk::{testutils::Address as _, Env, Address}; -use veilend_hello::*; - -#[test] -fn test_initialize() { - let env = Env::default(); - let contract_id = env.register(VeilLendHelloContract, ()); - let client = VeilLendHelloClient::new(&env, &contract_id); - - let admin = Address::generate(&env); - - // Initialize with admin - env.mock_all_auths(); - client.initialize(&admin); - - // Verify admin is set - assert_eq!(client.get_admin(), admin); -} - -#[test] -fn test_hello() { - let env = Env::default(); - let contract_id = env.register(VeilLendHelloContract, ()); - let client = VeilLendHelloClient::new(&env, &contract_id); - - let admin = Address::generate(&env); - env.mock_all_auths(); - client.initialize(&admin); - - let user = Address::generate(&env); - let result = client.hello(&user); - - assert_eq!(result, symbol_short!("Hello!")); -} -``` - -### 5. Build the Contract - -```bash -# Build the contract (compiles to WASM) -soroban contract build - -# Output will be in: -# target/wasm32-unknown-unknown/release/veilend_hello.wasm -``` - -### 6. Deploy to Local Network - -```bash -# Ensure local network is running (see Step 3) - -# Deploy the contract -soroban contract deploy \ - --wasm target/wasm32-unknown-unknown/release/veilend_hello.wasm \ - --source bob \ - --network local - -# This will output a contract ID (save it!) -# Example: CDZQYNS4K7QZ3VQXJ2X5G3JZQZ3VQXJ2X5G3JZQZ3VQXJ2X5G3JZQA -``` - -### 7. Invoke the Contract - -```bash -# Set your contract ID -export CONTRACT_ID="your_contract_id_here" - -# Initialize the contract -soroban contract invoke \ - --id $CONTRACT_ID \ - --source bob \ - --network local \ - -- \ - initialize \ - --admin bob - -# Call hello function -soroban contract invoke \ - --id $CONTRACT_ID \ - --source bob \ - --network local \ - -- \ - hello \ - --user bob - -# Get admin address -soroban contract invoke \ - --id $CONTRACT_ID \ - --source bob \ - --network local \ - -- \ - get_admin -``` - -### 8. Run Tests - -```bash -# Run all tests -cargo test - -# Run specific test -cargo test test_initialize - -# Run with output -cargo test -- --nocapture -``` - ---- - -## 💻 Essential VS Code Extensions - -Visual Studio Code is the recommended IDE for Soroban development. Install these extensions: - -### Required Extensions - -| Extension | Publisher | Purpose | Install Command | -| -------------------- | --------- | ------------------------------------------------ | -------------------------------------- | -| **rust-analyzer** | rust-lang | Rust language server (autocomplete, diagnostics) | `ext install rust-lang.rust-analyzer` | -| **Even Better TOML** | tamasfe | TOML file syntax highlighting | `ext install tamasfe.even-better-toml` | -| **CodeLLDB** | vadimcn | Debugger for Rust | `ext install vadimcn.vscode-lldb` | - -### Recommended Extensions - -| Extension | Publisher | Purpose | Install Command | -| --------------------- | ---------- | ------------------------- | --------------------------------------- | -| **crates** | serayuzgur | Manage Cargo dependencies | `ext install serayuzgur.crates` | -| **Error Lens** | usernamehw | Inline error highlighting | `ext install usernamehw.error-lens` | -| **GitLens** | eamodio | Enhanced Git capabilities | `ext install eamodio.gitlens` | -| **Prettier** | esbenp | Code formatting | `ext install esbenp.prettier-vscode` | -| **Soroban Contracts** | Stellar | Soroban-specific snippets | `ext install stellar.soroban-contracts` | - -### Install All Extensions at Once - -Create a `.vscode/extensions.json` file in your workspace: - -```json -{ - "recommendations": [ - "rust-lang.rust-analyzer", - "tamasfe.even-better-toml", - "vadimcn.vscode-lldb", - "serayuzgur.crates", - "usernamehw.error-lens", - "eamodio.gitlens", - "esbenp.prettier-vscode" - ] -} -``` - -Then install with: - -```bash -code --install-extension rust-lang.rust-analyzer -code --install-extension tamasfe.even-better-toml -code --install-extension vadimcn.vscode-lldb -code --install-extension serayuzgur.crates -code --install-extension usernamehw.error-lens -code --install-extension eamodio.gitlens -code --install-extension esbenp.prettier-vscode -``` - -### VS Code Settings - -Create `.vscode/settings.json`: - -```json -{ - "rust-analyzer.cargo.features": "all", - "rust-analyzer.checkOnSave.command": "clippy", - "rust-analyzer.procMacro.enable": true, - "editor.formatOnSave": true, - "editor.defaultFormatter": "rust-lang.rust-analyzer", - "[rust]": { - "editor.defaultFormatter": "rust-lang.rust-analyzer" - }, - "files.associations": { - "*.rs": "rust" - } -} -``` - ---- - -## 🛠️ Development Tools & Workflow - -### Essential Cargo Commands - -```bash -# Build contract -cargo build --target wasm32-unknown-unknown --release - -# Run tests -cargo test - -# Run tests with output -cargo test -- --nocapture - -# Format code -cargo fmt - -# Run linter -cargo clippy -- -D warnings - -# Check for security issues -cargo audit - -# Update dependencies -cargo update -``` - -### Soroban CLI Commands Reference - -```bash -# Network Management -soroban network ls # List networks -soroban network add # Add network -soroban network remove # Remove network - -# Account Management -soroban keys generate # Generate keypair -soroban keys fund # Fund account (testnet/local) -soroban keys balance # Check balance -soroban keys address # Get public key -soroban keys ls # List all keys -soroban keys rm # Remove key - -# Contract Management -soroban contract build # Build WASM -soroban contract deploy # Deploy contract -soroban contract invoke # Call contract function -soroban contract read # Read contract storage -soroban contract asset deploy # Deploy SAC (Stellar Asset Contract) - -# Utility -soroban lab xdr # XDR encoding/decoding -soroban lab token # Token utilities -``` - -### Development Workflow - -``` -1. Write Code → src/lib.rs -2. Format & Lint → cargo fmt && cargo clippy -3. Run Tests → cargo test -4. Build WASM → soroban contract build -5. Deploy to Local → soroban contract deploy --network local -6. Test Manually → soroban contract invoke -7. Deploy to Testnet → soroban contract deploy --network testnet -8. Verify on Explorer → https://stellar.expert/explorer/testnet/contract/ -``` - ---- - -## ⚡ Quick Start: Build & Test - -Here's a complete workflow to get you started: - -### 1. Clone VeilLend Repository - -```bash -git clone https://github.com/your-org/veillend.git -cd veillend/veilend-soroban -``` - -### 2. Install Dependencies - -```bash -# Install Rust dependencies -cargo fetch -``` - -### 3. Run Existing Tests - -```bash -# Run all tests -cargo test - -# Expected output: -# running X tests -# test test_initialize ... ok -# test test_hello ... ok -# -# test result: ok. X passed; 0 failed; 0 ignored; 0 measured; 0 filtered out -``` - -### 4. Build All Contracts - -```bash -soroban contract build - -# Verify WASM files were created -ls -lh target/wasm32-unknown-unknown/release/*.wasm -``` - -### 5. Start Local Network - -```bash -# In a separate terminal -docker run --rm -it \ - -p 8000:8000 \ - -p 5432:5432 \ - stellar/quickstart:testing \ - --standalone \ - --enable-soroban-rpc -``` - -### 6. Deploy & Test - -```bash -# Setup local account -soroban keys generate dev --network local -soroban keys fund dev --network local - -# Deploy contract -soroban contract deploy \ - --wasm target/wasm32-unknown-unknown/release/veilend_hello.wasm \ - --source dev \ - --network local - -# Invoke functions -soroban contract invoke \ - --id \ - --source dev \ - --network local \ - -- \ - initialize \ - --admin dev -``` - ---- - -## 🐛 Common Issues & Troubleshooting - -### Issue 1: Rust Installation Fails - -**Error:** `rustup: command not found` - -**Solution:** - -```bash -# Download and install rustup manually -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -source $HOME/.cargo/env -``` - ---- - -### Issue 2: WASM Target Not Found - -**Error:** `error[E0463]: can't find crate for core` - -**Solution:** - -```bash -# Install the WASM target -rustup target add wasm32-unknown-unknown - -# Verify -rustup target list --installed | grep wasm32 -``` - ---- - -### Issue 3: Soroban CLI Not Found - -**Error:** `soroban: command not found` - -**Solution:** - -```bash -# Add Cargo bin directory to PATH -echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc -source ~/.zshrc - -# Or reinstall -cargo install --locked soroban-cli -``` - ---- - -### Issue 4: Docker Container Won't Start - -**Error:** `port is already allocated` - -**Solution:** - -```bash -# Find and kill process using port 8000 -lsof -i :8000 -kill -9 - -# Or use different port -docker run --rm -it \ - -p 8001:8000 \ - stellar/quickstart:testing \ - --standalone \ - --enable-soroban-rpc -``` - ---- - -### Issue 5: Contract Deployment Fails - -**Error:** `insufficient balance` or `transaction failed` - -**Solution:** - -```bash -# Check account balance -soroban keys balance --network - -# Fund account (testnet) -soroban keys fund --network testnet - -# Fund account (local - unlimited) -soroban keys fund --network local -``` - ---- - -### Issue 6: Tests Fail with Panic - -**Error:** `panicked at 'called Option::unwrap() on a None value'` - -**Solution:** - -- Check that all storage values are initialized before reading -- Use `expect()` with descriptive error messages -- Add `env.mock_all_auths()` in tests to bypass authentication - ---- - -### Issue 7: Contract Build Fails - -**Error:** `compilation failed` or linker errors - -**Solution:** - -```bash -# Update Rust toolchain -rustup update - -# Clean and rebuild -cargo clean -soroban contract build - -# Check for dependency conflicts -cargo tree -``` - ---- - -### Issue 8: Local Network Connection Refused - -**Error:** `connection refused` or `timeout` - -**Solution:** - -```bash -# Check if Docker container is running -docker ps | grep quickstart - -# Wait for network to fully initialize (can take 30-60 seconds) -# Look for: "soroban rpc: listening on port 8000" - -# Test connection -curl http://localhost:8000/soroban/rpc -X POST \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","id":1,"method":"getHealth","params":[]}' -``` - ---- - -## 🎓 Next Steps - -Now that your environment is set up, here's what to do next: - -### 1. Study the Migration Guide - -Read the comprehensive Starknet → Soroban mapping: - -```bash -cat veilend_contracts/docs/migration/contract-mapping.md -``` - -**Key sections:** - -- Storage patterns (Cairo Maps → Soroban DataKey) -- Library equivalents (OpenZeppelin → Soroban) -- Type system mapping -- Event system mapping - -### 2. Review Existing Cairo Contracts - -Understand the current implementation: - -```bash -ls veilend_contracts/src/contracts/ -# lending_pool.cairo -# shielded_pool.cairo -# price_oracle.cairo -# reserve_data.cairo -# interest_token.cairo -# addresses_provider.cairo -``` - -### 3. Start with a Simple Contract - -Begin porting a simple contract like `addresses_provider.cairo` to Soroban: - -```bash -# Create new contract directory -cd veilend-soroban -soroban contract init addresses_provider -cd addresses_provider - -# Start implementing based on migration guide -``` - -### 4. Join the Community - -- **Discord:** [Stellar Developers](https://discord.gg/stellardev) -- **Documentation:** [Soroban Docs](https://soroban.stellar.org/docs) -- **Examples:** [Soroban Examples](https://github.com/stellar/soroban-examples) -- **Forum:** [Stellar Community Forum](https://community.stellar.org/) - -### 5. Contribute to VeilLend - -1. **Pick an Issue:** Check GitHub issues labeled `good-first-issue` or `soroban` -2. **Create a Branch:** `git checkout -b feature/soroban-lending-pool` -3. **Implement & Test:** Follow the development workflow above -4. **Submit a PR:** Include tests and documentation updates - ---- - -## 📚 Additional Resources - -### Official Documentation - -- [Soroban Documentation](https://soroban.stellar.org/docs) -- [Stellar Developer Docs](https://developers.stellar.org/docs) -- [Soroban SDK Reference](https://docs.rs/soroban-sdk/latest/soroban_sdk/) -- [Stellar SDK JS](https://stellar.github.io/js-stellar-sdk/) - -### Learning Resources - -- [Soroban Examples Repository](https://github.com/stellar/soroban-examples) - - `token` - Fungible token implementation - - `crowdfund` - Crowdfunding contract - - `timelock` - Timelock contract - - `auction` - Auction contract - - `cross_contract` - Cross-contract calls - -- [Awesome Soroban](https://github.com/stellar/awesome-soroban) -- [Soroban Workshop](https://github.com/stellar/soroban-workshop) - -### Tools & Libraries - -| Tool | Description | Link | -| --------------------- | --------------------------------- | ------------------------------------------ | -| **soroban-sdk** | Core SDK for contract development | https://crates.io/crates/soroban-sdk | -| **stellar-cli** | Command-line tools | https://github.com/stellar/stellar-cli | -| **soroban-token-sdk** | Token helper utilities | https://crates.io/crates/soroban-token-sdk | -| **stellar-sdk** | JavaScript SDK for frontend | https://github.com/stellar/js-stellar-sdk | -| **stellar-explore** | Block explorer | https://stellar.expert | - -### Community - -- **Discord:** [Stellar Developers](https://discord.gg/stellardev) -- **Stack Exchange:** [Stellar Stack Exchange](https://stellar.stackexchange.com/) -- **Reddit:** [r/stellar](https://reddit.com/r/stellar) -- **Twitter:** [@StellarOrg](https://twitter.com/StellarOrg) - -### VeilLend Specific Resources - -- **Project README:** `/README.md` -- **Starknet Contracts:** `/veilend_contracts/src/contracts/` -- **Migration Guide:** `/veilend_contracts/docs/migration/contract-mapping.md` -- **Backend API:** `/veilend-backend/` -- **Mobile App:** `/veilend-mobile/` - ---- - -## 📝 Quick Reference Card - -``` -┌─────────────────────────────────────────────────────┐ -│ SOROBAN DEVELOPMENT CHEAT SHEET │ -├─────────────────────────────────────────────────────┤ -│ Install: │ -│ rustup target add wasm32-unknown-unknown │ -│ cargo install --locked soroban-cli │ -│ │ -│ Build: │ -│ soroban contract build │ -│ │ -│ Deploy: │ -│ soroban contract deploy --wasm --source │ -│ │ -│ Invoke: │ -│ soroban contract invoke --id -- --fn │ -│ │ -│ Test: │ -│ cargo test │ -│ │ -│ Networks: │ -│ local: http://localhost:8000/soroban/rpc │ -│ testnet: https://soroban-testnet.stellar.org │ -│ mainnet: https://soroban-mainnet.stellar.org │ -└─────────────────────────────────────────────────────┘ -``` - ---- - -## ✅ Setup Checklist - -Use this checklist to verify your environment is ready: - -- [ ] Rust installed (`rustc --version`) -- [ ] WASM target installed (`rustup target list --installed | grep wasm32`) -- [ ] Soroban CLI installed (`soroban --version`) -- [ ] Docker installed (`docker --version`) -- [ ] Local network running (`docker ps | grep quickstart`) -- [ ] Testnet account created and funded -- [ ] Local account created and funded -- [ ] VS Code extensions installed -- [ ] Hello World contract built and tested -- [ ] Hello World contract deployed to local network -- [ ] Contract functions invoked successfully -- [ ] Read migration guide (`contract-mapping.md`) - ---- - -**Welcome to the VeilLend contributor community! 🎉** - -If you encounter any issues not covered here, please: - -1. Check the [troubleshooting section](#common-issues--troubleshooting) -2. Search existing GitHub issues -3. Ask in the Stellar Discord -4. Open a new issue with details about your problem - -Happy coding! 🚀 diff --git a/legacy/docs/migration/mobile-stellar-integration.md b/legacy/docs/migration/mobile-stellar-integration.md deleted file mode 100644 index 1109187..0000000 --- a/legacy/docs/migration/mobile-stellar-integration.md +++ /dev/null @@ -1,1428 +0,0 @@ -# Mobile Integration Guide: Stellar SDK in React Native - -**Document Status:** Production-Ready Research -**Last Updated:** May 2026 -**Target Platform:** Expo React Native (iOS/Android/Web) -**Difficulty:** Easy (Frontend Research & Implementation) - ---- - -## Table of Contents - -1. [Executive Summary](#executive-summary) -2. [Current Architecture Overview](#current-architecture-overview) -3. [Stellar Wallet Integration Options](#stellar-wallet-integration-options) -4. [Implementation Strategy](#implementation-strategy) -5. [Architecture Changes](#architecture-changes) -6. [UI/UX Updates](#uiux-updates) -7. [Code Examples](#code-examples) -8. [Migration Path](#migration-path) -9. [Testing & Validation](#testing--validation) -10. [Deployment Checklist](#deployment-checklist) - ---- - -## Executive Summary - -This guide provides a comprehensive roadmap for integrating Stellar wallets into the existing Veillend mobile application. The current implementation supports Starknet through `@starknet-react/core` with multiple wallet connectors (Argent X, Braavos, Web Wallet). Stellar integration follows a parallel architecture pattern, maintaining backward compatibility while enabling cross-chain functionality. - -**Key Deliverables:** -- Multi-chain wallet provider architecture -- Stellar wallet integration (Freighter recommendation) -- Unified transaction signing interface -- Dual-address support (Starknet + Stellar) -- Backend authentication updates - ---- - -## Current Architecture Overview - -### Stack Overview -``` -Technology Version Purpose -───────────────────────────────────────────────── -Expo ~54.0.33 Development framework -React Native 0.81.5 Mobile runtime -@starknet-react ^5.0.3 Starknet provider -starknetkit ^3.4.3 Wallet connectors -zustand ^5.0.11 State management -expo-secure-store ~15.0.8 Secure credential storage -``` - -### Current Flow (Starknet) -``` -User → ConnectWalletScreen - → useConnect() + starknetkitConnectModal - → Wallet Selection (Argent X, Braavos, Web Wallet) - → Wallet Connection - → Store address in zustand + SecureStore - → requestNonce(address) - → signMessage(typedData) - → verify(address, signature, typedData) - → JWT token issued -``` - -### Authentication Flow (Backend) -```typescript -// Current: Starknet signature verification -1. generateNonce() → Creates random nonce with 5min expiry -2. verifySignature() → Validates StarkNet typed-data signature using ec.starkCurve -3. login() → Issues JWT token -``` - -**Key File Structure:** -- `App.tsx` - StarknetConfig provider setup -- `src/screens/ConnectWalletScreen.tsx` - Wallet connection UI -- `src/store/store.ts` - Zustand state management (Auth, Lending, Shielded) -- `src/utils/api.ts` - Backend API client -- Backend `src/auth/auth.service.ts` - Signature verification - ---- - -## Stellar Wallet Integration Options - -### Library Comparison Matrix - -| Criteria | Freighter | Albedo | RWallet | Notes | -|----------|-----------|--------|---------|-------| -| **React Native Support** | ✅ Yes (via WalletConnect) | ⚠️ Limited | ⚠️ Limited | Native Expo support critical | -| **TypeScript Support** | ✅ Full | ✅ Full | ✅ Full | Development experience | -| **XDR Signing** | ✅ Yes | ✅ Yes | ✅ Yes | Transaction building | -| **Network Support** | Mainnet/Testnet | Mainnet/Testnet | Mainnet/Testnet | Stellar ecosystem standard | -| **WalletConnect v2** | ✅ Yes | ✅ Yes | ✅ Yes | Mobile first approach | -| **Documentation** | ✅ Excellent | ⚠️ Fair | ⚠️ Fair | Community maturity | -| **Active Maintenance** | ✅ Yes | ✅ Yes | ⚠️ Dormant | Long-term support | -| **Community Size** | ✅ Large | ✅ Medium | ⚠️ Small | Issue resolution speed | -| **Mobile Testing** | ✅ Extensive | ⚠️ Limited | ⚠️ Limited | Production readiness | - -### Recommendation: **Freighter + WalletConnect v2** - -**Rationale:** -1. **Native Expo Support**: Freighter works reliably in React Native via WalletConnect v2 bridge protocol -2. **Market Dominance**: 60%+ of Stellar mobile wallet market share -3. **XDR Handling**: Native support for complex transaction building and signing -4. **Developer Experience**: Comprehensive TypeScript types and documentation -5. **Network Flexibility**: Seamless testnet/mainnet switching -6. **Fallback Options**: WalletConnect v2 enables RWallet/Albedo as fallback connectors - ---- - -## Implementation Strategy - -### Phase 1: Foundation (Backend Preparation) - -#### 1.1 Install Dependencies -```bash -cd veilend-backend -npm install --save stellar-sdk @stellar/js-sdk-admin -# For XDR validation -npm install --save base64-js -``` - -#### 1.2 Update Backend Auth Service -Add Stellar signature verification alongside existing Starknet verification: - -```typescript -// src/auth/auth.service.ts - Add Stellar verification - -import { Keypair, TransactionBuilder } from '@stellar/js-sdk-admin'; - -async verifyStellarSignature( - address: string, - signature: string, - xdrTransaction: string, - publicKey: string -): Promise { - const user = await this.usersService.findOne(address); - if (!user || !user.nonce) { - throw new UnauthorizedException('Nonce not found'); - } - - // Check nonce expiry - if (user['nonce_expires_at'] && Date.now() > Number(user['nonce_expires_at'])) { - throw new UnauthorizedException('Nonce expired'); - } - - try { - // Decode XDR transaction - const transaction = TransactionBuilder.fromXDR(xdrTransaction, 'TESTNET'); - - // Extract memo from transaction - const memoValue = transaction.memo.value || ''; - if (String(memoValue) !== String(user.nonce)) { - throw new UnauthorizedException('Invalid nonce in transaction'); - } - - // Verify signature - const keypair = Keypair.fromPublicKey(publicKey); - const isValid = keypair.verify( - Buffer.from(xdrTransaction), - Buffer.from(signature, 'base64') - ); - - if (!isValid) { - throw new UnauthorizedException('Invalid Stellar signature'); - } - - // Clear nonce to prevent replay attacks - await this.usersService.createOrUpdate(address, { - nonce: null, - nonce_expires_at: null - }); - - return user; - } catch (e) { - this.logger.error('Stellar signature verification failed', e); - throw new UnauthorizedException('Stellar signature verification failed'); - } -} -``` - -#### 1.3 Add Chain Detection to Users Service -```typescript -// src/users/users.service.ts - Add chain field - -type UserWithChain = { - address: string; - chain: 'starknet' | 'stellar'; // New field - nonce: string; - nonce_expires_at: number; - // ... other fields -}; - -async createOrUpdate(address: string, chain: string, data: any): Promise { - return this.db.users.upsert({ - where: { address_chain: { address, chain } }, - create: { address, chain, ...data }, - update: data, - }); -} -``` - -#### 1.4 Update Auth Controller -```typescript -// src/auth/auth.controller.ts - Add Stellar endpoint - -@Post('/verify') -async verify(@Body() body: { address: string; chain: string; signature: string; typedData?: any; xdr?: string }) { - if (body.chain === 'starknet') { - const user = await this.authService.verifySignature( - body.address, - body.signature, - body.typedData, - body.address // publicKey - ); - return this.authService.login(user); - } else if (body.chain === 'stellar') { - const user = await this.authService.verifyStellarSignature( - body.address, - body.signature, - body.xdr, - body.address - ); - return this.authService.login(user); - } - throw new BadRequestException('Unsupported chain'); -} -``` - ---- - -### Phase 2: Mobile Frontend Implementation - -#### 2.1 Install Dependencies -```bash -cd veilend-mobile -npm install --save \ - @stellar/js-sdk-mobile \ - @walletconnect/react-native-compat \ - @walletconnect/modal-react-native \ - react-native-url-polyfill \ - events - -npm install --save-dev @types/stellar-sdk -``` - -#### 2.2 Update App.tsx - Add Stellar Provider -```typescript -// App.tsx - -import React from 'react'; -import { StarknetConfig, jsonRpcProvider } from "@starknet-react/core"; -import { sepolia } from "@starknet-react/chains"; -import { InjectedConnector } from "starknetkit/injected"; -import { ArgentMobileConnector } from "starknetkit/argentMobile"; -import { WebWalletConnector } from "starknetkit/webwallet"; -import WalletConnectModal from "@walletconnect/modal-react-native"; -import { useWalletConnectModal } from "@walletconnect/modal-react-native"; -import RootNavigator from './src/navigation'; -import { StatusBar } from 'expo-status-bar'; -import { View, StyleSheet, ActivityIndicator } from 'react-native'; -import Toast from './src/utils/toast'; -import { useStore } from './src/store/store'; -import { GestureHandlerRootView } from 'react-native-gesture-handler'; -import Animated from "react-native-reanimated"; - -// Polyfill setup -import 'react-native-url-polyfill/auto'; -import 'react-native-get-random-values'; - -const chains = [sepolia]; -const provider = jsonRpcProvider({ - rpc: (chain) => ({ - nodeUrl: 'https://starknet-sepolia.public.blastapi.io' - }) -}); - -const starknetConnectors = [ - new InjectedConnector({ options: { id: "argentX" } }), - new InjectedConnector({ options: { id: "braavos" } }), - new ArgentMobileConnector(), - new WebWalletConnector({ url: "https://web.argent.xyz" }), -]; - -const walletConnectProjectId = process.env.EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID || 'YOUR_PROJECT_ID'; - -export default function App() { - const authLoading = useStore((s) => s.authLoading); - const lendingLoading = useStore((s) => s.lendingLoading); - const shieldedLoading = useStore((s) => s.shieldedLoading); - const anyLoading = authLoading || lendingLoading || shieldedLoading; - - return ( - - - - - - - - {anyLoading && ( - - - - )} - - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { flex: 1, backgroundColor: '#000' }, - loadingOverlay: { - position: 'absolute', - top: 0, left: 0, right: 0, bottom: 0, - backgroundColor: 'rgba(0,0,0,0.7)', - justifyContent: 'center', - alignItems: 'center', - }, -}); -``` - -#### 2.3 Create Stellar Wallet Hook -```typescript -// src/hooks/useStellarWallet.ts - -import { useCallback, useState } from 'react'; -import { useWalletConnectModal } from '@walletconnect/modal-react-native'; -import { Keypair, TransactionBuilder, BASE_FEE, Networks } from '@stellar/js-sdk-mobile'; - -export interface StellarWallet { - address: string; - publicKey: string; - network: 'testnet' | 'mainnet'; -} - -export interface SignXdrResult { - xdr: string; - signature: string; -} - -export const useStellarWallet = () => { - const { open, isOpen, provider } = useWalletConnectModal(); - const [wallet, setWallet] = useState(null); - const [isConnecting, setIsConnecting] = useState(false); - - const connect = useCallback(async () => { - try { - setIsConnecting(true); - - // Open WalletConnect modal - if (!isOpen) { - await open({ - route: 'SelectNetwork' - }); - } - - // Wait for wallet to be connected via WalletConnect - if (provider) { - // Subscribe to account_changed events - provider.on('display_uri', (uri: string) => { - console.log('WalletConnect URI:', uri); - }); - - provider.on('session_created', async (payload: any) => { - const accounts = payload.params.namespaces?.stellar?.accounts || []; - if (accounts.length > 0) { - const account = accounts[0]; // stellar:testnet:GXXXXXX - const [, network, address] = account.split(':'); - - setWallet({ - address, - publicKey: address, - network: network as 'testnet' | 'mainnet', - }); - } - }); - } - } catch (error) { - console.error('Failed to connect Stellar wallet:', error); - throw error; - } finally { - setIsConnecting(false); - } - }, [open, isOpen, provider]); - - const signXDR = useCallback(async (xdrString: string): Promise => { - if (!provider || !wallet) { - throw new Error('Wallet not connected'); - } - - try { - const response = await provider.request({ - method: 'stellar_signXDR', - params: { - xdr: xdrString, - publicKeys: [wallet.publicKey], - }, - }); - - return { - xdr: response.xdr, - signature: response.signature, - }; - } catch (error) { - console.error('Failed to sign XDR:', error); - throw error; - } - }, [provider, wallet]); - - const disconnect = useCallback(() => { - setWallet(null); - if (provider) { - provider.disconnect(); - } - }, [provider]); - - return { - wallet, - connect, - disconnect, - signXDR, - isConnecting, - isConnected: !!wallet, - }; -}; -``` - -#### 2.4 Update Zustand Store - Multi-Chain Support -```typescript -// src/store/store.ts - Enhanced version - -import { create } from 'zustand'; -import api from '../utils/api'; -import * as SecureStoreShim from '../utils/secureStoreShim'; - -let SecureStore: typeof SecureStoreShim; -try { - SecureStore = require('expo-secure-store'); -} catch (e) { - SecureStore = SecureStoreShim as any; -} - -type Chain = 'starknet' | 'stellar'; -type Nullable = T | null; - -type AuthState = { - // Multi-chain support - chain: Nullable; - address: Nullable; - starknetAddress: Nullable; - stellarAddress: Nullable; - - authToken: Nullable; - - setChain: (chain: Chain) => void; - setAddress: (address: string | null, chain?: Chain) => void; - setAuthToken: (token: string | null) => void; - logout: () => void; - - // Multi-chain nonce & verify - requestNonce: (address: string, chain: Chain) => Promise; - verify: (payload: { - address: string; - chain: Chain; - signature?: any; - typedData?: any; - xdr?: string; - publicKey?: string; - }) => Promise; - - authLoading: boolean; -}; - -type UiState = { - isPrivacyMode: boolean; - togglePrivacyMode: () => void; -}; - -type LendingState = { - lastLendingTx: Nullable; - lendingLoading: boolean; - deposit: (params: { amount: string; asset: string }) => Promise; - withdraw: (params: { amount: string; asset: string }) => Promise; - borrow: (params: { amount: string; asset: string }) => Promise; - repay: (params: { amount: string; asset: string }) => Promise; -}; - -type ShieldedState = { - lastShieldedTx: Nullable; - shieldedLoading: boolean; - depositShielded: (params: any) => Promise; - withdrawShielded: (params: any) => Promise; -}; - -export const useStore = create((set, get) => ({ - // Auth - Multi-chain - chain: null, - address: null, - starknetAddress: null, - stellarAddress: null, - authToken: null, - authLoading: false, - - setChain: (chain: Chain) => { - set({ chain }); - try { SecureStore.setItemAsync('chain', chain); } catch (e) {} - }, - - setAddress: (address: string | null, chain?: Chain) => { - const activeChain = chain || get().chain; - - if (activeChain === 'starknet') { - set({ starknetAddress: address, address }); - } else if (activeChain === 'stellar') { - set({ stellarAddress: address, address }); - } - - try { - if (address) { - SecureStore.setItemAsync(`address_${activeChain}`, address); - SecureStore.setItemAsync('address', address); - } else { - SecureStore.deleteItemAsync(`address_${activeChain}`); - } - } catch (e) {} - }, - - setAuthToken: (token: string | null) => { - set({ authToken: token }); - try { - if (token) SecureStore.setItemAsync('authToken', token); - else SecureStore.deleteItemAsync('authToken'); - } catch (e) {} - }, - - logout: () => { - set({ - address: null, - starknetAddress: null, - stellarAddress: null, - authToken: null, - chain: null, - isPrivacyMode: false, - }); - try { SecureStore.deleteItemAsync('authToken'); } catch (e) {} - }, - - // UI - isPrivacyMode: false, - togglePrivacyMode: () => set((state) => ({ isPrivacyMode: !state.isPrivacyMode })), - - // Async helpers (Auth) - Multi-chain - requestNonce: async (address: string, chain: Chain) => { - const res = await api.post(`/auth/nonce?address=${address}&chain=${chain}`); - return res.data?.nonce; - }, - - verify: async ({ address, chain, signature, typedData, xdr, publicKey }) => { - set({ authLoading: true }); - try { - const payload: any = { address, chain }; - - if (chain === 'starknet') { - payload.signature = signature; - payload.typedData = typedData; - payload.publicKey = publicKey; - } else if (chain === 'stellar') { - payload.signature = signature; - payload.xdr = xdr; - } - - const res = await api.post('/auth/verify', payload); - const token = res.data?.access_token || null; - - set({ authLoading: false, authToken: token, address, chain }); - try { if (token) SecureStore.setItemAsync('authToken', token); } catch (e) {} - - return token; - } catch (err) { - set({ authLoading: false }); - throw err; - } - }, - - // Lending - lastLendingTx: null, - lendingLoading: false, - deposit: async (params) => { - // Existing implementation - return null; - }, - withdraw: async (params) => { - // Existing implementation - return null; - }, - borrow: async (params) => { - // Existing implementation - return null; - }, - repay: async (params) => { - // Existing implementation - return null; - }, - - // Shielded - lastShieldedTx: null, - shieldedLoading: false, - depositShielded: async (params) => { - // Existing implementation - return null; - }, - withdrawShielded: async (params) => { - // Existing implementation - return null; - }, -})); -``` - -#### 2.5 Create Transaction Builder Utility -```typescript -// src/utils/stellar.ts - -import { - Keypair, - TransactionBuilder, - Networks, - BASE_FEE, - Operation, -} from '@stellar/js-sdk-mobile'; - -export const buildAuthTransaction = ( - publicKey: string, - nonce: string, - network: 'testnet' | 'mainnet' = 'testnet' -): string => { - const keypair = Keypair.fromPublicKey(publicKey); - const networkPassphrase = network === 'testnet' - ? Networks.TESTNET_NETWORK_PASSPHRASE - : Networks.PUBLIC_NETWORK_PASSPHRASE; - - const account = new Account(keypair.publicKey(), '0'); - - const transaction = new TransactionBuilder(account, { - fee: BASE_FEE, - networkPassphrase, - timebounds: { - minTime: 0, - maxTime: Math.floor(Date.now() / 1000) + 600, // 10 minutes - }, - }) - .addMemo(TransactionBuilder.memo(nonce)) // Nonce stored in memo - .addOperation( - Operation.manageBuyOffer({ - selling: Asset.native(), - buying: Asset.native(), - buyAmount: '0', // Dummy operation for authentication - price: '1', - }) - ) - .build(); - - return transaction.toXDR(); -}; - -export const parseSignedXDR = (signedXdr: string) => { - try { - const transaction = TransactionBuilder.fromXDR(signedXdr, 'TESTNET'); - return { - valid: true, - memo: transaction.memo, - operations: transaction.operations.length, - }; - } catch (e) { - return { valid: false, error: String(e) }; - } -}; -``` - ---- - -### Phase 3: UI/UX Implementation - -#### 3.1 Enhanced ConnectWalletScreen -```typescript -// src/screens/ConnectWalletScreen.tsx - Multi-chain version - -import React, { useState } from 'react'; -import { - View, - Text, - TouchableOpacity, - StyleSheet, - Dimensions, - ScrollView, -} from 'react-native'; -import { useStellarWallet } from '../hooks/useStellarWallet'; -import { useConnect, useAccount } from '@starknet-react/core'; -import { useStarknetkitConnectModal } from 'starknetkit'; -import { useStore } from '../store/store'; -import { buildAuthTransaction, parseSignedXDR } from '../utils/stellar'; -import Toast from '../utils/toast'; -import { LinearGradient } from 'expo-linear-gradient'; -import { Ionicons } from '@expo/vector-icons'; - -const { width } = Dimensions.get('window'); - -type WalletOption = 'starknet' | 'stellar' | null; - -export default function ConnectWalletScreen() { - const [selectedWallet, setSelectedWallet] = useState(null); - - // Starknet - const { connect: starknetConnect, connectors } = useConnect(); - const { address: starknetAddr, account } = useAccount(); - const { starknetkitConnectModal } = useStarknetkitConnectModal({ - connectors: connectors as any, - modalTheme: 'dark', - dappName: 'VeilLend', - }); - - // Stellar - const { - wallet: stellarWallet, - connect: stellarConnect, - signXDR, - isConnecting: stellarConnecting, - } = useStellarWallet(); - - const { setAddress, setChain, requestNonce, verify } = useStore(); - - // Starknet authentication flow - const handleStarknetConnect = async () => { - try { - setSelectedWallet('starknet'); - const { connector } = await starknetkitConnectModal(); - if (connector) { - await starknetConnect({ connector }); - } - } catch (error: any) { - Toast.show({ - type: 'error', - text1: 'Connection Failed', - text2: error?.message || 'Could not connect to Starknet wallet', - }); - setSelectedWallet(null); - } - }; - - // Starknet sign & verify (existing logic) - React.useEffect(() => { - if (starknetAddr && account && selectedWallet === 'starknet') { - authenticateStarknet(); - } - }, [starknetAddr, account, selectedWallet]); - - const authenticateStarknet = async () => { - try { - if (!starknetAddr || !account) return; - - setChain('starknet'); - setAddress(starknetAddr); - - const nonce = await requestNonce(starknetAddr, 'starknet'); - - const typedData = { - types: { - StarkNetDomain: [ - { name: 'name', type: 'felt' }, - { name: 'version', type: 'felt' }, - { name: 'chainId', type: 'felt' }, - ], - Message: [{ name: 'nonce', type: 'felt' }], - }, - primaryType: 'Message', - domain: { - name: 'VeilLend', - version: '1', - chainId: '0x534e5f5345504f4c4941', // SN_SEPOLIA - }, - message: { nonce }, - }; - - const signature = await account.signMessage(typedData); - const token = await verify({ - address: starknetAddr, - chain: 'starknet', - signature, - typedData, - publicKey: starknetAddr, - }); - - if (token) { - Toast.show({ - type: 'success', - text1: 'Connected', - text2: `Starknet: ${starknetAddr.slice(0, 8)}...`, - }); - } - } catch (error: any) { - Toast.show({ - type: 'error', - text1: 'Authentication Failed', - text2: error?.message || 'Could not sign message', - }); - } - }; - - // Stellar authentication flow - const handleStellarConnect = async () => { - try { - setSelectedWallet('stellar'); - await stellarConnect(); - - if (stellarWallet) { - await authenticateStellar(); - } - } catch (error: any) { - Toast.show({ - type: 'error', - text1: 'Connection Failed', - text2: error?.message || 'Could not connect to Stellar wallet', - }); - setSelectedWallet(null); - } - }; - - const authenticateStellar = async () => { - try { - if (!stellarWallet) return; - - setChain('stellar'); - setAddress(stellarWallet.address); - - const nonce = await requestNonce(stellarWallet.address, 'stellar'); - - // Build transaction with nonce in memo - const xdrString = buildAuthTransaction( - stellarWallet.publicKey, - nonce, - stellarWallet.network - ); - - // Sign XDR - const { xdr, signature } = await signXDR(xdrString); - - // Verify signature - const token = await verify({ - address: stellarWallet.address, - chain: 'stellar', - signature, - xdr, - }); - - if (token) { - Toast.show({ - type: 'success', - text1: 'Connected', - text2: `Stellar: ${stellarWallet.address.slice(0, 8)}...`, - }); - } - } catch (error: any) { - Toast.show({ - type: 'error', - text1: 'Authentication Failed', - text2: error?.message || 'Could not sign transaction', - }); - } - }; - - return ( - - - - - Choose Your Blockchain - Select a wallet to continue - - {/* Starknet Option */} - - - - - Starknet - - - Fast, scalable transactions with ZK proofs - - - {['Argent X', 'Braavos', 'Web Wallet'].map((w) => ( - • {w} - ))} - - - - - {/* Stellar Option */} - - - - - Stellar - - - Cross-chain interoperability and XDR standards - - - {['Freighter', 'Albedo', 'RWallet'].map((w) => ( - • {w} - ))} - - - - - {/* Info Box */} - - - - You can switch blockchains anytime. Your assets will be network-specific. - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#000', - }, - content: { - padding: 16, - paddingTop: 60, - paddingBottom: 40, - }, - title: { - fontSize: 28, - fontWeight: '700', - color: '#FFF', - marginBottom: 8, - }, - subtitle: { - fontSize: 14, - color: '#999', - marginBottom: 32, - }, - blockchainCard: { - marginBottom: 16, - borderRadius: 16, - overflow: 'hidden', - borderWidth: 2, - borderColor: 'transparent', - }, - selectedCard: { - borderColor: '#09CC71', - backgroundColor: 'rgba(9, 204, 113, 0.1)', - }, - cardGradient: { - padding: 20, - }, - cardHeader: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 12, - }, - blockchainIcon: { - marginRight: 12, - }, - blockchainName: { - fontSize: 20, - fontWeight: '700', - color: '#FFF', - }, - blockchainDesc: { - fontSize: 13, - color: '#BBB', - marginBottom: 16, - }, - walletList: { - borderTopWidth: 1, - borderTopColor: 'rgba(255,255,255,0.1)', - paddingTop: 12, - }, - walletItem: { - fontSize: 12, - color: '#999', - marginVertical: 4, - }, - infoBox: { - flexDirection: 'row', - backgroundColor: 'rgba(9, 204, 113, 0.15)', - padding: 16, - borderRadius: 12, - marginTop: 24, - }, - infoText: { - fontSize: 12, - color: '#09CC71', - marginLeft: 12, - flex: 1, - }, -}); -``` - ---- - -## Architecture Changes - -### 1. Database Schema Updates - -```sql --- Add chain support to users table -ALTER TABLE users ADD COLUMN chain VARCHAR(50) DEFAULT 'starknet'; -ALTER TABLE users ADD CONSTRAINT unique_address_chain UNIQUE(address, chain); - --- Add index for faster lookups -CREATE INDEX idx_user_chain ON users(chain); -CREATE INDEX idx_user_address_chain ON users(address, chain); - --- Add Stellar-specific fields -ALTER TABLE users ADD COLUMN stellar_public_key VARCHAR(56); -ALTER TABLE users ADD COLUMN stellar_network VARCHAR(20) DEFAULT 'testnet'; -``` - -### 2. State Management Architecture - -``` -┌─────────────────────────────────────┐ -│ useStore (Zustand) │ -├─────────────────────────────────────┤ -│ Auth State (Multi-chain) │ -│ - chain: 'starknet' | 'stellar' │ -│ - address: current address │ -│ - starknetAddress: archived │ -│ - stellarAddress: archived │ -│ - authToken: JWT │ -│ │ -│ UI State │ -│ - isPrivacyMode │ -│ │ -│ Lending State │ -│ - Multi-chain compatible │ -│ │ -│ Shielded State │ -│ - Starknet only (for now) │ -└─────────────────────────────────────┘ -``` - -### 3. Wallet Provider Architecture - -```typescript -WalletProvider (Experimental - future multi-chain wrapper) -├── StarknetProvider (@starknet-react/core) -│ ├── Connector: InjectedConnector (Argent X) -│ ├── Connector: InjectedConnector (Braavos) -│ ├── Connector: ArgentMobileConnector -│ └── Connector: WebWalletConnector -└── StellarProvider (WalletConnect v2) - ├── Connector: Freighter (via WalletConnect) - ├── Connector: Albedo (via WalletConnect) - └── Connector: RWallet (via WalletConnect) -``` - ---- - -## UI/UX Updates - -### 1. ConnectWalletScreen - Multi-Chain Selection -- **Layout**: Card-based blockchain selection (Starknet vs Stellar) -- **Visual Hierarchy**: Clear differentiation between chains -- **User Flow**: Select chain → Select wallet → Connect → Sign -- **Fallback UI**: "Continue without wallet" for dev/testing - -### 2. DashboardScreen - Dual Address Display -``` -┌─────────────────────────────┐ -│ Account Information │ -├─────────────────────────────┤ -│ Active Chain: [Starknet ▼] │ -│ Address: 0x123...ABCD │ -│ │ -│ [Switch to Stellar] [Copy] │ -│ │ -│ Linked Addresses: │ -│ • Starknet: 0x123... │ -│ • Stellar: GXXXXXX... │ -└─────────────────────────────┘ -``` - -### 3. TransactionHistoryScreen - Network Badges -``` -Transaction Network Time Status -─────────────────────────────────────────────── -Deposit 100 USDC [Starknet] 2h ago ✓ Complete -Bridge to Stellar [Stellar] 1d ago ✓ Complete -Borrow 50 ETH [Starknet] 3d ago ✓ Complete -``` - -### 4. SettingsScreen - Chain Management -- Display linked wallets -- Allow unlinking individual chains -- Network switching (testnet ↔ mainnet) -- Logout by chain - ---- - -## Code Examples - -### Example 1: Multi-Chain Transaction Flow -```typescript -// Usage in a lending component -import { useStore } from '../store/store'; - -export const DepositScreen = () => { - const { address, chain, authLoading, deposit } = useStore(); - - const handleDeposit = async (amount: string, asset: string) => { - if (!address || !chain) { - showToast('Please connect a wallet first'); - return; - } - - try { - // Backend automatically routes based on chain stored with authToken - const result = await deposit({ amount, asset }); - showToast(`Deposit successful on ${chain}`); - } catch (error) { - showToast(`Failed: ${error.message}`); - } - }; - - return ( - - Active: {chain} - {address} - - - - - - {/* --- LAYER 1: PROTOCOL RISK ENGINE OVERVIEW --- */} - {!isEmpty && !isLoading && ( -
- - - Net Account Value - $124,500.00 USDC - - - - - Collateral Factor Health - 78.4% - - - - - - - - Current Borrow Limit Utilization - 42.1% - - - - - -
- )} - - {/* --- LAYER 2: PRIMARY DATA GRIDS --- */} -
- - {/* SECTION A: SHIELDED ASSET BALANCES */} - - -
- - Shielded Liquidity Balances - - USDC / XLM Only -
- Your current unencumbered assets residing within zero-knowledge layers. -
- - {isLoading ? ( -
- - -
- ) : isEmpty ? ( -
-
- -
-

No shielded assets detected. Initialize a private transfer payload sequence to populate your balance limits.

-
- ) : ( -
-
-
-
U
-
-
USD Coin (Stellar Asset)
-
USDC
-
-
-
-
150,000.00
-
$150,000.00
-
-
-
-
-
X
-
-
Native Lumens
-
XLM
-
-
-
-
85,400.00
-
$11,102.00
-
-
-
- )} -
-
- - {/* SECTION B: COLLATERAL & CREDIT BORROWING TRACKS */} - - -
- - Debt & Collateralized Ratios - - Risk Engine -
- Active debt obligations measured against locked credit collateral pools. -
- - {isLoading ? ( -
- -
- ) : isEmpty ? ( -
-
- -
-

No current leverage parameters active. Lock collateral into a private Soroban contract framework to open lines of credit.

-
- ) : ( -
-
-
- Total Collateral Deposited -
$50,000.00
-
-
- Active Borrowed Liabilities -
$21,050.00
-
-
- -
-
- - Liquidation Point Safeguard Matrix - - 85.00% Max Threshold -
-
- -
-
-
-
- )} - - -
- - {/* --- LAYER 3: REAL-TIME CRYPTOGRAPHIC ACTIVITY LOGS --- */} - - -
- - Cryptographic Ledger Audit Log - - Live Handshakes Stream -
- Real-time status tracking of structural interactions across the VeilLend core. -
- - {isLoading ? ( -
- - -
- ) : isEmpty ? ( -
- No historical zero-knowledge proof evaluations or balance mutations exist on this account scope. -
- ) : ( -
- - - - - - - - - - - - - - - - - - - - -
Operation ActionExecution StatusBlock Sequence
- Shielded Balance Allocation Inbound - - ZK_PROOF_VERIFIED - #5829141
- Collateral Lock Allocation Call - - SOROBAN_SUCCESS - #5829023
-
- )} -
-
-
- ) -} \ No newline at end of file diff --git a/veilend-web/src/app/api/campaign-events/route.ts b/veilend-web/src/app/api/campaign-events/route.ts deleted file mode 100644 index b45fc90..0000000 --- a/veilend-web/src/app/api/campaign-events/route.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { NextResponse } from 'next/server'; - -const campaignEvents = [ - 'campaign_page_visit', - 'campaign_cta_click', - 'campaign_contributor_interest', -] as const; - -type CampaignEventName = (typeof campaignEvents)[number]; - -type CampaignEventRequest = { - event?: CampaignEventName; - campaign?: string; - timestamp?: string; - payload?: Record; -}; - -type SanitizedPayload = { - path?: string; - referrer?: string; - source?: string; - ctaId?: string; - ctaLabel?: string; - targetUrl?: string; - interestArea?: string; -}; - -function isCampaignEventName(event: unknown): event is CampaignEventName { - return typeof event === 'string' && campaignEvents.includes(event as CampaignEventName); -} - -function sanitizeString(value: unknown, maxLength = 160) { - if (typeof value !== 'string') { - return undefined; - } - - const trimmedValue = value.trim(); - - if (!trimmedValue) { - return undefined; - } - - return trimmedValue.slice(0, maxLength); -} - -function sanitizePayload(payload: CampaignEventRequest['payload']): SanitizedPayload { - if (!payload) { - return {}; - } - - return { - path: sanitizeString(payload.path), - referrer: sanitizeString(payload.referrer, 240), - source: sanitizeString(payload.source), - ctaId: sanitizeString(payload.ctaId), - ctaLabel: sanitizeString(payload.ctaLabel), - targetUrl: sanitizeString(payload.targetUrl, 240), - interestArea: sanitizeString(payload.interestArea), - }; -} - -export async function POST(request: Request) { - let body: CampaignEventRequest; - - try { - body = await request.json(); - } catch { - return NextResponse.json({ error: 'Invalid JSON payload' }, { status: 400 }); - } - - if (!isCampaignEventName(body.event) || body.campaign !== 'grantfox-oss-stellar') { - return NextResponse.json({ error: 'Unsupported campaign event' }, { status: 400 }); - } - - const analyticsEvent = { - event: body.event, - campaign: body.campaign, - timestamp: sanitizeString(body.timestamp) ?? new Date().toISOString(), - payload: sanitizePayload(body.payload), - }; - - console.info('[campaign-analytics]', analyticsEvent); - - return NextResponse.json({ ok: true }); -} diff --git a/veilend-web/src/app/dashboard/error.tsx b/veilend-web/src/app/dashboard/error.tsx deleted file mode 100644 index 1e32bba..0000000 --- a/veilend-web/src/app/dashboard/error.tsx +++ /dev/null @@ -1,42 +0,0 @@ -'use client'; - -import { useEffect } from 'react'; -import { Container, Flex, Section } from '@/components/Layout'; -import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; -import { Button } from '@/components/ui/button'; - -export default function DashboardError({ - error, - reset, -}: { - error: Error & { digest?: string }; - reset: () => void; -}) { - useEffect(() => { - // Log the error to an error reporting service - console.error('Dashboard failed to load:', error); - }, [error]); - - return ( -
- -
- - - Failed to load dashboard - - We encountered an error while fetching your live portfolio and activity data. - Please try again or check your network connection. - - -
- -
-
-
-
-
- ); -} diff --git a/veilend-web/src/app/dashboard/loading.tsx b/veilend-web/src/app/dashboard/loading.tsx deleted file mode 100644 index 181f0d8..0000000 --- a/veilend-web/src/app/dashboard/loading.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Container, Flex, Grid, Section } from '@/components/Layout'; -import { LoaderCircle } from 'lucide-react'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Skeleton } from '@/components/ui/skeleton'; - -export default function DashboardLoading() { - return ( -
- -
- - -

Dashboard

- -
-

Fetching live portfolio data...

-
-
- -
- - {[1, 2, 3].map((i) => ( - - - - - - - - - - ))} - -
- -
- - - Recent Activity - - - - {[1, 2, 3, 4].map((i) => ( - - - -
- - -
-
- -
- ))} -
-
-
-
-
-
- ); -} diff --git a/veilend-web/src/app/dashboard/page.tsx b/veilend-web/src/app/dashboard/page.tsx deleted file mode 100644 index 317708c..0000000 --- a/veilend-web/src/app/dashboard/page.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { Container, Flex, Grid, Section } from '@/components/Layout'; -import { Badge } from '@/components/ui/badge'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { fetchDashboardData } from '@/lib/api/dashboard'; - -export const dynamic = 'force-dynamic'; - -export default async function DashboardPage() { - const data = await fetchDashboardData(); - const { portfolio, recentActivity } = data; - - const getActionBadgeClassName = (action: string) => { - switch (action) { - case 'DEPOSIT': - return 'border-emerald-500/20 bg-emerald-500/10 text-emerald-400'; - case 'BORROW': - return 'border-amber-500/20 bg-amber-500/10 text-amber-400'; - case 'REPAY': - return 'border-purple-500/20 bg-purple-500/10 text-purple-400'; - case 'WITHDRAW': - return 'border-cyan-500/20 bg-cyan-500/10 text-cyan-400'; - default: - return undefined; - } - }; - - const formatUsd = (val: number) => - new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(val); - - return ( -
- -
- -
-

Live Dashboard

-

- Overview of your Stellar network portfolio and recent activity. -

-
-
-
- - {/* Portfolio Section */} -
- - - - Total Balance - - -
- {formatUsd(portfolio.totalBalanceUsd)} -
-
-
- - - - Total Deposited - - -
- {formatUsd(portfolio.totalDepositedUsd)} -
-
-
- - - - - Total Borrowed - - Health: {portfolio.healthFactor.toFixed(2)} - - - - -
- {formatUsd(portfolio.totalBorrowedUsd)} -
-
-
-
-
- - {/* Asset Breakdown */} -
- - - - Deposited Assets - - - {portfolio.depositedAssets.length === 0 ? ( -

No deposited assets.

- ) : ( - - {portfolio.depositedAssets.map((asset) => ( - - -
- {asset.assetSymbol.charAt(0)} -
-
-
{asset.assetName}
-
- {asset.balance.toLocaleString()} {asset.assetSymbol} -
-
-
-
{formatUsd(asset.usdValue)}
-
- ))} -
- )} -
-
- - - - Borrowed Assets - - - {portfolio.borrowedAssets.length === 0 ? ( -

No borrowed assets.

- ) : ( - - {portfolio.borrowedAssets.map((asset) => ( - - -
- {asset.assetSymbol.charAt(0)} -
-
-
{asset.assetName}
-
- {asset.balance.toLocaleString()} {asset.assetSymbol} -
-
-
-
{formatUsd(asset.usdValue)}
-
- ))} -
- )} -
-
-
-
- - {/* Recent Activity */} -
- - - Recent Activity - - - {recentActivity.length === 0 ? ( -

No recent activity found.

- ) : ( - - {recentActivity.map((activity) => ( - - -
- - - {activity.action} - - - {activity.amount.toLocaleString()} {activity.assetSymbol} - - -
- {new Date(activity.timestamp).toLocaleString()} -
-
-
-
-
- {formatUsd(activity.usdValue)} -
-
- {activity.status.toLowerCase()} -
-
-
- ))} -
- )} -
-
-
-
-
- ); -} diff --git a/veilend-web/src/app/favicon.ico b/veilend-web/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m diff --git a/veilend-web/src/app/globals.css b/veilend-web/src/app/globals.css deleted file mode 100644 index 5edaf63..0000000 --- a/veilend-web/src/app/globals.css +++ /dev/null @@ -1,161 +0,0 @@ -@import "tailwindcss"; -@import "tw-animate-css"; -@import "shadcn/tailwind.css"; - -@custom-variant dark (&:is(.dark *)); - -:root { - --veil-primary: #A855F7; - --veil-primary-hover: #9333EA; - --veil-secondary: #00D1FF; - --veil-secondary-hover: #00B8E6; - --veil-background: #0A0A0A; - --veil-background-alt: #141414; - --veil-card: #1A1A1A; - --veil-card-hover: #252525; - --veil-text: #FFFFFF; - --veil-text-secondary: #A1A1A1; - --veil-text-muted: #6B7280; - --veil-border: #2D2D2D; - --veil-success: #10B981; - --veil-warning: #F59E0B; - --veil-error: #EF4444; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.87 0 0); - --chart-2: oklch(0.556 0 0); - --chart-3: oklch(0.439 0 0); - --chart-4: oklch(0.371 0 0); - --chart-5: oklch(0.269 0 0); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -@theme inline { - --color-primary: var(--veil-primary); - --color-primary-hover: var(--veil-primary-hover); - --color-secondary: var(--veil-secondary); - --color-secondary-hover: var(--veil-secondary-hover); - --color-background: var(--veil-background); - --color-background-alt: var(--veil-background-alt); - --color-card: var(--veil-card); - --color-card-hover: var(--veil-card-hover); - --color-text: var(--veil-text); - --color-text-secondary: var(--veil-text-secondary); - --color-text-muted: var(--veil-text-muted); - --color-border: var(--veil-border); - --color-success: var(--veil-success); - --color-warning: var(--veil-warning); - --color-error: var(--veil-error); - --font-sans: var(--font-sans); - --font-mono: var(--font-geist-mono); - --radius-sm: 0.375rem; - --radius-md: 0.5rem; - --radius-lg: 0.75rem; - --radius-xl: 1rem; - --shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2); - --font-heading: var(--font-sans); - --color-sidebar-ring: var(--sidebar-ring); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar: var(--sidebar); - --color-chart-5: var(--chart-5); - --color-chart-4: var(--chart-4); - --color-chart-3: var(--chart-3); - --color-chart-2: var(--chart-2); - --color-chart-1: var(--chart-1); - --color-ring: var(--ring); - --color-input: var(--input); - --color-destructive: var(--destructive); - --color-accent-foreground: var(--accent-foreground); - --color-accent: var(--accent); - --color-muted-foreground: var(--muted-foreground); - --color-muted: var(--muted); - --color-secondary-foreground: var(--secondary-foreground); - --color-primary-foreground: var(--primary-foreground); - --color-popover-foreground: var(--popover-foreground); - --color-popover: var(--popover); - --color-card-foreground: var(--card-foreground); - --color-foreground: var(--foreground); - --radius-2xl: calc(var(--radius) * 1.8); - --radius-3xl: calc(var(--radius) * 2.2); - --radius-4xl: calc(var(--radius) * 2.6); -} - -body { - background: var(--veil-background); - color: var(--veil-text); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.87 0 0); - --chart-2: oklch(0.556 0 0); - --chart-3: oklch(0.439 0 0); - --chart-4: oklch(0.371 0 0); - --chart-5: oklch(0.269 0 0); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } - html { - @apply font-sans; - } -} \ No newline at end of file diff --git a/veilend-web/src/app/layout.tsx b/veilend-web/src/app/layout.tsx deleted file mode 100644 index ee6dc58..0000000 --- a/veilend-web/src/app/layout.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type { Metadata } from 'next'; -import { Geist, Geist_Mono, Inter } from 'next/font/google'; -import './globals.css'; -import { cn } from "@/lib/utils"; -import { WalletProvider } from '@/context/WalletContext'; - -const inter = Inter({ subsets: ['latin'], variable: '--font-sans' }); - -const geistSans = Geist({ - variable: '--font-geist-sans', - subsets: ['latin'], -}); - -const geistMono = Geist_Mono({ - variable: '--font-geist-mono', - subsets: ['latin'], -}); - -export const metadata: Metadata = { - title: 'VeilLend | GrantFox Campaign', - description: - 'Privacy-first contributor campaign for building VeilLend on Stellar with anonymous first-party analytics.', -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - - - {children} - - - - ); -} \ No newline at end of file diff --git a/veilend-web/src/app/page.tsx b/veilend-web/src/app/page.tsx deleted file mode 100644 index 80f60fc..0000000 --- a/veilend-web/src/app/page.tsx +++ /dev/null @@ -1,255 +0,0 @@ -'use client' - -import * as React from "react" -import Link from "next/link" -import { - Shield, - ArrowRight, - EyeOff, - Cpu, - CheckCircle2, - ChevronRight, - TrendingUp, - Terminal -} from "lucide-react" -import { Button } from "@/components/ui/button" -import { Card, CardContent } from "@/components/ui/card" -import { Badge } from "@/components/ui/badge" -import { useWallet } from "@/context/WalletContext" - -export default function VeilLendLandingPage() { - const { isConnected, isAuthenticated } = useWallet(); - // Simulated Live Campaign Metrics for the contributor block - const [totalContributed, setTotalContributed] = React.useState(642850) - - React.useEffect(() => { - const interval = setInterval(() => { - setTotalContributed(prev => prev + Math.floor(Math.random() * 45) + 5) - }, 4000) - return () => clearInterval(interval) - }, []) - - return ( -
- - {/* Decorative Cyber Grid Background & Radial Ambient Glows */} -
-
-
- - {/* HERO SECTION */} -
-
- - - VeilLend Contributor Campaign Is Live - -
- -

- The Next Generation of Private Liquidity on Stellar -

- -

- VeilLend bridges standard Soroban smart contracts with advanced zero-knowledge primitives. Borrow, lend, and deploy capital seamlessly with absolute balance protection and uncompromised regulatory readiness. -

- -
- {isConnected && isAuthenticated ? ( - - ) : ( - - )} - -
- - {/* Dynamic Abstract Code Terminal Frame Mockup */} -
-
-
- - - - soroban_client_initialization.rs -
- -
-
-

use soroban_sdk::{"{Env, Address, symbol_short};"}

-

use veillend_zk_proofs::{"{verify_proof, FixedPointMath};"}

-

Initialize shielded vault interface configurations

-

pub fn execute_shielded_deposit(env: Env, contributor: Address, commitment: i128) {"{"}

-

assert_minimum_stroop_threshold!(commitment);

-

let proof_is_valid = verify_proof(&env, &contributor);

-

env.storage().instance().set(&symbol_short!("status"), &proof_is_valid);

-

{"}"}

-
-
-
- - {/* LIVE CAMPAIGN METRICS PANEL */} -
-
-
-
- Live Statistics -
-

Contributor Campaign Pool

-

Early participants anchor the root liquidity metrics for matching asset pools.

-
-
- Total Seeded Assets -
${totalContributed.toLocaleString()} USDC
-
-
- Active Guard Handshakes -
1,482 Wallets
-
-
-
- - {/* CORE FEATURES MATRIX */} -
-
-

Engineered for Absolute Confidentiality

-

- VeilLend introduces modern mathematical structures directly into standard Soroban transactions, optimizing throughput speed while prioritizing enterprise-grade compliance layers. -

-
- -
- {/* Feature Card 1 */} - - -
- -
-

Shielded Positions

-

- Execute lending allocations and capture compounding interest rates without broadcasting your capital sizing variables or personal treasury parameters to public ledger scanners. -

-
-
- - {/* Feature Card 2 */} - - -
- -
-

Soroban Optimizations

-

- Built natively inside the Stellar virtual machine layer. Take advantage of deterministic transaction compute consumption fees, millisecond transaction settlement loops, and ultra-low storage footprints. -

-
-
- - {/* Feature Card 3 */} - - -
- -
-

Compliant by Design

-

- Utilize view-key architecture options to effortlessly share cryptographically verifiable position tracking records with tax advisors, compliance managers, or internal regulatory systems. -

-
-
-
-
- - {/* PROTOCOL ROADMAP MILESTONES */} -
-
-

Development Timeline

-

- Track our execution trajectory as we deploy privacy-preserving smart contract infrastructure. -

-
- -
- {/* Milestone item 1 */} -
-
- -
-
- Phase 1 - Completed -
-

Foundational Infrastructure Core

-

- Established core virtual workspaces, fixed-point precision math processing engines, and early zero-knowledge circuits testing profiles. -

-
- - {/* Milestone item 2 */} -
-
- 2 -
-
- Phase 2 - Active Track -
-

Contributor Campaign Launch

-

- Opening public interfaces to aggregate initial seed commitments for testing structural load boundaries under realistic market configurations. -

-
- - {/* Milestone item 3 */} -
-
- 3 -
- Phase 3 -

Mainnet Smart Contract Deployment

-

- Full external code auditing integration tracking, public multi-asset vault provisioning, and official open liquidity governance controls initialization. -

-
-
-
- - {/* CTA CLOSING SUMMARY */} -
-
-
-

Ready to Secure Your Yield Pipeline?

-

- Secure early platform allocation status metrics, qualify for priority liquidity distribution brackets, and support privacy-first decentralization. -

-
- {isConnected && isAuthenticated ? ( - - ) : ( - - )} -
-
-
- - {/* VISUAL FOOTER */} -
-
© 2026 VeilLend Protocol Ecosystem. All rights reserved.
-
- Architecture - Stellar Foundation - Security Disclosures -
-
-
- ) -} \ No newline at end of file diff --git a/veilend-web/src/components/AmountInput.tsx b/veilend-web/src/components/AmountInput.tsx deleted file mode 100644 index 16cc862..0000000 --- a/veilend-web/src/components/AmountInput.tsx +++ /dev/null @@ -1,122 +0,0 @@ -'use client' - -import * as React from 'react'; -import { Input } from '@/components/ui/input'; -import { cn } from '@/lib/utils'; -import { ActivityActionType } from '@/lib/types/dashboard'; -import { - validateAmount, - parseAmount, - ValidationContext, - ValidationResult, -} from '@/lib/validation/amount'; - -interface AmountInputProps { - action: ActivityActionType; - context: ValidationContext; - assetSymbol: string; - value: string; - onChange: (value: string) => void; - /** Called whenever validity changes so the parent can enable/disable submit */ - onValidityChange?: (result: ValidationResult) => void; - disabled?: boolean; -} - -/** - * Controlled amount input with inline validation for protocol actions. - * Blocks submission on errors and surfaces non-blocking risk/balance warnings. - */ -export function AmountInput({ - action, - context, - assetSymbol, - value, - onChange, - onValidityChange, - disabled, -}: AmountInputProps) { - const [touched, setTouched] = React.useState(false); - - const result = React.useMemo( - () => validateAmount(action, value, context), - [action, value, context], - ); - - React.useEffect(() => { - onValidityChange?.(result); - }, [result, onValidityChange]); - - const showFeedback = touched && value.trim() !== '' && result.message; - const isError = result.severity === 'error'; - - const handleMax = () => { - const max = - action === 'REPAY' && context.outstandingDebt !== undefined - ? Math.min(context.outstandingDebt, context.availableBalance) - : context.availableBalance; - onChange(String(max)); - setTouched(true); - }; - - const parsed = parseAmount(value); - const usdPreview = - parsed !== null && parsed > 0 - ? new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( - parsed * context.priceUsd, - ) - : null; - - return ( -
-
- { - onChange(e.target.value); - if (!touched) setTouched(true); - }} - onBlur={() => setTouched(true)} - className="pr-24 font-mono" - /> -
- - {assetSymbol} -
-
- -
- {showFeedback ? ( - - {result.message} - - ) : ( - - )} - {usdPreview && !isError && ( - ≈ {usdPreview} - )} -
-
- ); -} diff --git a/veilend-web/src/components/CampaignTracker.tsx b/veilend-web/src/components/CampaignTracker.tsx deleted file mode 100644 index f327e65..0000000 --- a/veilend-web/src/components/CampaignTracker.tsx +++ /dev/null @@ -1,14 +0,0 @@ -'use client'; - -import { useEffect } from 'react'; -import { trackCampaignEvent } from '@/lib/campaignAnalytics'; - -export function CampaignTracker() { - useEffect(() => { - trackCampaignEvent('campaign_page_visit', { - referrer: document.referrer || undefined, - }); - }, []); - - return null; -} diff --git a/veilend-web/src/components/ContributorInterest.tsx b/veilend-web/src/components/ContributorInterest.tsx deleted file mode 100644 index 8afb41d..0000000 --- a/veilend-web/src/components/ContributorInterest.tsx +++ /dev/null @@ -1,55 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { trackCampaignEvent } from '@/lib/campaignAnalytics'; - -const interestAreas = [ - 'Soroban contracts', - 'Web app', - 'Mobile app', - 'Privacy research', - 'Docs and onboarding', -]; - -export function ContributorInterest() { - const [selectedArea, setSelectedArea] = useState(null); - - return ( -
-

- Contributor interest -

-

Tell us where you want to help

-

- Pick an area to record anonymized campaign interest before jumping into GitHub. -

-
- {interestAreas.map((interestArea) => ( - - ))} -
- {selectedArea ? ( -

- Interest tracked for {selectedArea}. No names, emails, wallet addresses, or cookies were - collected. -

- ) : null} -
- ); -} diff --git a/veilend-web/src/components/Layout.tsx b/veilend-web/src/components/Layout.tsx deleted file mode 100644 index 41870b3..0000000 --- a/veilend-web/src/components/Layout.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React from "react"; - -interface ContainerProps { - children: React.ReactNode; - className?: string; -} - -export const Container: React.FC = ({ - children, - className = "", -}) => { - return ( -
- {children} -
- ); -}; - -interface SectionProps { - children: React.ReactNode; - className?: string; -} - -export const Section: React.FC = ({ - children, - className = "", -}) => { - return
{children}
; -}; - -interface FlexProps { - children: React.ReactNode; - direction?: "row" | "col"; - justify?: "start" | "center" | "end" | "between" | "around"; - align?: "start" | "center" | "end" | "stretch"; - gap?: "none" | "sm" | "md" | "lg" | "xl"; - wrap?: boolean; - className?: string; -} - -export const Flex: React.FC = ({ - children, - direction = "row", - justify = "start", - align = "start", - gap = "md", - wrap = false, - className = "", -}) => { - const directionClasses: Record = { - row: "flex-row", - col: "flex-col", - }; - - const justifyClasses: Record = { - start: "justify-start", - center: "justify-center", - end: "justify-end", - between: "justify-between", - around: "justify-around", - }; - - const alignClasses: Record = { - start: "items-start", - center: "items-center", - end: "items-end", - stretch: "items-stretch", - }; - - const gapClasses: Record = { - none: "gap-0", - sm: "gap-2", - md: "gap-4", - lg: "gap-6", - xl: "gap-8", - }; - - return ( -
- {children} -
- ); -}; - -interface GridProps { - children: React.ReactNode; - columns?: number; - gap?: "none" | "sm" | "md" | "lg" | "xl"; - className?: string; -} - -export const Grid: React.FC = ({ - children, - columns = 1, - gap = "md", - className = "", -}) => { - const gapClasses: Record = { - none: "gap-0", - sm: "gap-2", - md: "gap-4", - lg: "gap-6", - xl: "gap-8", - }; - - const columnClasses: Record = { - 1: "grid-cols-1", - 2: "grid-cols-1 md:grid-cols-2", - 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3", - 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4", - }; - - return ( -
- {children} -
- ); -}; diff --git a/veilend-web/src/components/SyncStatusBadge.tsx b/veilend-web/src/components/SyncStatusBadge.tsx deleted file mode 100644 index d161e9f..0000000 --- a/veilend-web/src/components/SyncStatusBadge.tsx +++ /dev/null @@ -1,100 +0,0 @@ -'use client' - -import * as React from 'react'; -import { RefreshCw, Wifi, WifiOff, AlertTriangle, CircleDashed } from 'lucide-react'; -import { cn } from '@/lib/utils'; -import { SyncStatus } from '@/lib/hooks/usePositionSync'; - -interface SyncStatusBadgeProps { - status: SyncStatus; - lastSyncedAt: number | null; - onRefresh?: () => void; -} - -/** - * Compact visual indicator of the live-sync state. Gives the user an at-a-glance - * sense of whether the numbers on screen are fresh, stale, or failing to update. - */ -export function SyncStatusBadge({ status, lastSyncedAt, onRefresh }: SyncStatusBadgeProps) { - const config = STATUS_CONFIG[status]; - const Icon = config.icon; - - return ( -
- - - {config.label} - - - {lastSyncedAt && (status === 'live' || status === 'stale') && ( - - {formatRelative(lastSyncedAt)} - - )} - - {onRefresh && ( - - )} -
- ); -} - -const STATUS_CONFIG: Record< - SyncStatus, - { label: string; icon: React.ComponentType<{ className?: string }>; className: string } -> = { - idle: { - label: 'Idle', - icon: CircleDashed, - className: 'border-slate-800 bg-slate-900/60 text-slate-500', - }, - loading: { - label: 'Syncing', - icon: RefreshCw, - className: 'border-indigo-500/20 bg-indigo-500/10 text-indigo-400', - }, - live: { - label: 'Live', - icon: Wifi, - className: 'border-emerald-500/20 bg-emerald-500/10 text-emerald-400', - }, - stale: { - label: 'Stale', - icon: AlertTriangle, - className: 'border-amber-500/20 bg-amber-500/10 text-amber-400', - }, - empty: { - label: 'No positions', - icon: CircleDashed, - className: 'border-slate-800 bg-slate-900/60 text-slate-500', - }, - error: { - label: 'Offline', - icon: WifiOff, - className: 'border-rose-500/20 bg-rose-500/10 text-rose-400', - }, -}; - -function formatRelative(ms: number): string { - const seconds = Math.floor((Date.now() - ms) / 1000); - if (seconds < 5) return 'just now'; - if (seconds < 60) return `${seconds}s ago`; - const minutes = Math.floor(seconds / 60); - if (minutes < 60) return `${minutes}m ago`; - const hours = Math.floor(minutes / 60); - return `${hours}h ago`; -} diff --git a/veilend-web/src/components/TrackedLink.tsx b/veilend-web/src/components/TrackedLink.tsx deleted file mode 100644 index 05c470e..0000000 --- a/veilend-web/src/components/TrackedLink.tsx +++ /dev/null @@ -1,46 +0,0 @@ -'use client'; - -import React from 'react'; -import { type VariantProps } from 'class-variance-authority'; -import { buttonVariants } from '@/components/ui/button'; -import { trackCampaignEvent } from '@/lib/campaignAnalytics'; -import { cn } from '@/lib/utils'; - -type TrackedLinkProps = React.AnchorHTMLAttributes & { - ctaId: string; - ctaLabel: string; - variant?: VariantProps['variant']; - size?: VariantProps['size']; - fullWidth?: boolean; -}; - -export function TrackedLink({ - ctaId, - ctaLabel, - href, - onClick, - className, - variant = 'default', - size = 'default', - fullWidth = false, - children, - ...props -}: TrackedLinkProps) { - return ( - { - trackCampaignEvent('campaign_cta_click', { - ctaId, - ctaLabel, - targetUrl: typeof href === 'string' ? href : undefined, - }); - onClick?.(event); - }} - {...props} - > - {children} - - ); -} diff --git a/veilend-web/src/components/WalletConnect.tsx b/veilend-web/src/components/WalletConnect.tsx deleted file mode 100644 index f31bf3f..0000000 --- a/veilend-web/src/components/WalletConnect.tsx +++ /dev/null @@ -1,172 +0,0 @@ -"use client"; - -import React, { useState } from "react"; -import { Wallet, X, ExternalLink } from "lucide-react"; -import { useWallet } from "@/context/WalletContext"; -import { Button } from "@/components/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; -import { Badge } from "@/components/ui/badge"; - -// Define the Freighter window interface -interface FreighterWindow extends Window { - freighter?: { - isConnected: () => Promise<{ isConnected: boolean }>; - getAddress: () => Promise<{ address: string }>; - signTransaction: (txXdr: string, opts?: { networkPassphrase?: string }) => Promise<{ signedTxXdr: string }>; - }; -} - -interface WalletConnectProps { - className?: string; - size?: "sm" | "default" | "lg"; -} - -export function WalletConnect({ className, size = "default" }: WalletConnectProps) { - const { address, isConnected, isAuthenticated, isLoading, error, connect, disconnect } = useWallet(); - const [isModalOpen, setIsModalOpen] = useState(false); - - const handleConnect = async () => { - await connect(); - if (!error) { - setIsModalOpen(false); - } - }; - - const handleDisconnect = async () => { - await disconnect(); - setIsModalOpen(false); - }; - - const truncatedAddress = address - ? `${address.slice(0, 6)}...${address.slice(-4)}` - : ""; - - // Wallet is connected - if (isConnected && isAuthenticated) { - return ( -
- - - {truncatedAddress} - - -
- ); - } - - // Wallet not connected - return ( - <> - - - - - - Connect Wallet - - Connect your Stellar wallet to access the VeilLend dashboard and manage your shielded assets. - - - -
- {/* Freighter Wallet Option */} -
-
-
- 🚀 -
-
-
Freighter Wallet
-
Stellar browser extension
-
-
- -
- - {/* Error Message */} - {error && ( -
- {error} -
- )} - - {/* Info Message */} - {!isFreighterInstalled() && ( -
-

- Freighter wallet not detected. - - Install Freighter - -

-
- )} -
- - -

- By connecting, you agree to the VeilLend Terms of Service. -

- -
-
-
- - ); -} - -/** - * Helper function to check if Freighter is installed - * This is exported for use in other components - */ -export const isFreighterInstalled = (): boolean => { - if (typeof window === "undefined") return false; - const win = window as FreighterWindow; - return typeof win.freighter !== "undefined"; -}; - -export default WalletConnect; \ No newline at end of file diff --git a/veilend-web/src/components/WalletStatus.tsx b/veilend-web/src/components/WalletStatus.tsx deleted file mode 100644 index 3efa241..0000000 --- a/veilend-web/src/components/WalletStatus.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client"; - -import React from "react"; -import { Wallet, ShieldCheck, ShieldAlert, Loader2 } from "lucide-react"; -import { useWallet } from "@/context/WalletContext"; -import { Badge } from "@/components/ui/badge"; - -interface WalletStatusProps { - showDetails?: boolean; - className?: string; -} - -export function WalletStatus({ showDetails = false, className = "" }: WalletStatusProps) { - const { address, isConnected, isAuthenticated, isLoading, error } = useWallet(); - - if (isLoading) { - return ( -
- - Initializing wallet... -
- ); - } - - if (error) { - return ( -
- - Wallet error - {showDetails && {error}} -
- ); - } - - if (isConnected && isAuthenticated) { - const truncatedAddress = address - ? `${address.slice(0, 6)}...${address.slice(-4)}` - : ""; - - return ( -
- - - Connected - - {showDetails && ( - {truncatedAddress} - )} -
- ); - } - - return ( -
- - Not connected -
- ); -} - -export default WalletStatus; \ No newline at end of file diff --git a/veilend-web/src/components/ui/alert.tsx b/veilend-web/src/components/ui/alert.tsx deleted file mode 100644 index b4d671a..0000000 --- a/veilend-web/src/components/ui/alert.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const alertVariants = cva( - "relative w-full rounded-lg border px-4 py-3 text-sm", - { - variants: { - variant: { - default: "bg-card text-card-foreground", - destructive: - "border-destructive/50 bg-destructive/10 text-destructive dark:border-destructive", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -function Alert({ - className, - variant, - ...props -}: React.ComponentProps<"div"> & VariantProps) { - return
-} - -function AlertTitle({ className, ...props }: React.ComponentProps<"h5">) { - return
-} - -function AlertDescription({ className, ...props }: React.ComponentProps<"div">) { - return
-} - -export { Alert, AlertDescription, AlertTitle } diff --git a/veilend-web/src/components/ui/badge.tsx b/veilend-web/src/components/ui/badge.tsx deleted file mode 100644 index cacff11..0000000 --- a/veilend-web/src/components/ui/badge.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" -import { Slot } from "radix-ui" - -import { cn } from "@/lib/utils" - -const badgeVariants = cva( - "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", - secondary: - "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", - destructive: - "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", - outline: - "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", - ghost: - "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", - link: "text-primary underline-offset-4 hover:underline", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -function Badge({ - className, - variant = "default", - asChild = false, - ...props -}: React.ComponentProps<"span"> & - VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot.Root : "span" - - return ( - - ) -} - -export { Badge, badgeVariants } diff --git a/veilend-web/src/components/ui/button.tsx b/veilend-web/src/components/ui/button.tsx deleted file mode 100644 index 6f9b6c1..0000000 --- a/veilend-web/src/components/ui/button.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" -import { Slot } from "radix-ui" - -import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/80", - outline: - "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50", - secondary: - "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", - ghost: - "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50", - destructive: - "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: - "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", - xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", - sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5", - lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", - icon: "size-9", - "icon-xs": - "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3", - "icon-sm": - "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md", - "icon-lg": "size-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) - -function Button({ - className, - variant = "default", - size = "default", - asChild = false, - ...props -}: React.ComponentProps<"button"> & - VariantProps & { - asChild?: boolean - }) { - const Comp = asChild ? Slot.Root : "button" - - return ( - - ) -} - -export { Button, buttonVariants } diff --git a/veilend-web/src/components/ui/card.tsx b/veilend-web/src/components/ui/card.tsx deleted file mode 100644 index fc9a740..0000000 --- a/veilend-web/src/components/ui/card.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -function Card({ - className, - size = "default", - ...props -}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) { - return ( -
img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl", - className - )} - {...props} - /> - ) -} - -function CardHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardTitle({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardDescription({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardAction({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardContent({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function CardFooter({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -export { - Card, - CardHeader, - CardFooter, - CardTitle, - CardAction, - CardDescription, - CardContent, -} diff --git a/veilend-web/src/components/ui/checkbox.tsx b/veilend-web/src/components/ui/checkbox.tsx deleted file mode 100644 index 9fa5bee..0000000 --- a/veilend-web/src/components/ui/checkbox.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client" - -import * as React from "react" -import { Checkbox as CheckboxPrimitive } from "radix-ui" - -import { cn } from "@/lib/utils" -import { CheckIcon } from "lucide-react" - -function Checkbox({ - className, - ...props -}: React.ComponentProps) { - return ( - - - - - - ) -} - -export { Checkbox } diff --git a/veilend-web/src/components/ui/dialog.tsx b/veilend-web/src/components/ui/dialog.tsx deleted file mode 100644 index 7caed7d..0000000 --- a/veilend-web/src/components/ui/dialog.tsx +++ /dev/null @@ -1,165 +0,0 @@ -"use client" - -import * as React from "react" -import { Dialog as DialogPrimitive } from "radix-ui" - -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { XIcon } from "lucide-react" - -function Dialog({ - ...props -}: React.ComponentProps) { - return -} - -function DialogTrigger({ - ...props -}: React.ComponentProps) { - return -} - -function DialogPortal({ - ...props -}: React.ComponentProps) { - return -} - -function DialogClose({ - ...props -}: React.ComponentProps) { - return -} - -function DialogOverlay({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function DialogContent({ - className, - children, - showCloseButton = true, - ...props -}: React.ComponentProps & { - showCloseButton?: boolean -}) { - return ( - - - - {children} - {showCloseButton && ( - - - - )} - - - ) -} - -function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -function DialogFooter({ - className, - showCloseButton = false, - children, - ...props -}: React.ComponentProps<"div"> & { - showCloseButton?: boolean -}) { - return ( -
- {children} - {showCloseButton && ( - - - - )} -
- ) -} - -function DialogTitle({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function DialogDescription({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogOverlay, - DialogPortal, - DialogTitle, - DialogTrigger, -} diff --git a/veilend-web/src/components/ui/input.tsx b/veilend-web/src/components/ui/input.tsx deleted file mode 100644 index 17beb1e..0000000 --- a/veilend-web/src/components/ui/input.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return ( - - ) -} - -export { Input } diff --git a/veilend-web/src/components/ui/progress.tsx b/veilend-web/src/components/ui/progress.tsx deleted file mode 100644 index d432b47..0000000 --- a/veilend-web/src/components/ui/progress.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client" - -import * as React from "react" -import { Progress as ProgressPrimitive } from "radix-ui" - -import { cn } from "@/lib/utils" - -function Progress({ - className, - value, - ...props -}: React.ComponentProps) { - return ( - - - - ) -} - -export { Progress } diff --git a/veilend-web/src/components/ui/separator.tsx b/veilend-web/src/components/ui/separator.tsx deleted file mode 100644 index d457090..0000000 --- a/veilend-web/src/components/ui/separator.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client" - -import * as React from "react" -import { Separator as SeparatorPrimitive } from "radix-ui" - -import { cn } from "@/lib/utils" - -function Separator({ - className, - orientation = "horizontal", - decorative = true, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { Separator } diff --git a/veilend-web/src/components/ui/skeleton.tsx b/veilend-web/src/components/ui/skeleton.tsx deleted file mode 100644 index 0118624..0000000 --- a/veilend-web/src/components/ui/skeleton.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { cn } from "@/lib/utils" - -function Skeleton({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) -} - -export { Skeleton } diff --git a/veilend-web/src/context/WalletContext.tsx b/veilend-web/src/context/WalletContext.tsx deleted file mode 100644 index e8ce72d..0000000 --- a/veilend-web/src/context/WalletContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client"; - -import React, { createContext, useContext, ReactNode } from "react"; -import { useStellarWallet, WalletState, WalletActions } from "@/hooks/useStellarWallet"; - -type WalletContextType = WalletState & WalletActions; - -const WalletContext = createContext(undefined); - -export function WalletProvider({ children }: { children: ReactNode }) { - const wallet = useStellarWallet(); - - return {children}; -} - -export function useWallet(): WalletContextType { - const context = useContext(WalletContext); - if (context === undefined) { - throw new Error("useWallet must be used within a WalletProvider"); - } - return context; -} - -export default WalletProvider; \ No newline at end of file diff --git a/veilend-web/src/hooks/useStellarWallet.ts b/veilend-web/src/hooks/useStellarWallet.ts deleted file mode 100644 index 663dab1..0000000 --- a/veilend-web/src/hooks/useStellarWallet.ts +++ /dev/null @@ -1,118 +0,0 @@ -"use client"; - -import { useState, useEffect, useCallback } from "react"; -import { isWalletAuthenticated, getAuthenticatedWallet, clearAuthSession, createAuthSession } from "@/lib/stellar/auth"; -import { connectFreighter, isFreighterInstalled, disconnectWallet } from "@/lib/stellar/wallet"; - -export interface WalletState { - address: string | null; - publicKey: string | null; - isConnected: boolean; - isAuthenticated: boolean; - isInstalled: boolean; - isLoading: boolean; - error: string | null; -} - -export interface WalletActions { - connect: () => Promise; - disconnect: () => Promise; - clearError: () => void; -} - -export function useStellarWallet(): WalletState & WalletActions { - const [state, setState] = useState({ - address: null, - publicKey: null, - isConnected: false, - isAuthenticated: false, - isInstalled: false, - isLoading: false, - error: null, - }); - - // Check authentication status and Freighter installation on mount - useEffect(() => { - const initializeWallet = () => { - const installed = isFreighterInstalled(); - const isAuth = isWalletAuthenticated(); - const address = getAuthenticatedWallet(); - - setState((prev) => ({ - ...prev, - isInstalled: installed, - address: isAuth ? address : null, - publicKey: isAuth ? address : null, - isConnected: isAuth && !!address, - isAuthenticated: isAuth && !!address, - })); - }; - - initializeWallet(); - }, []); - - const connect = useCallback(async () => { - if (state.isLoading) return; - - setState((prev) => ({ ...prev, isLoading: true, error: null })); - - try { - const wallet = await connectFreighter(); - - // Create auth session - createAuthSession(wallet.address, wallet.publicKey); - - setState((prev) => ({ - ...prev, - address: wallet.address, - publicKey: wallet.publicKey, - isConnected: true, - isAuthenticated: true, - isLoading: false, - error: null, - })); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Failed to connect wallet"; - setState((prev) => ({ - ...prev, - isLoading: false, - error: errorMessage, - isConnected: false, - isAuthenticated: false, - })); - } - }, [state.isLoading]); - - const disconnect = useCallback(async () => { - try { - await disconnectWallet(); - clearAuthSession(); - - setState((prev) => ({ - ...prev, - address: null, - publicKey: null, - isConnected: false, - isAuthenticated: false, - error: null, - })); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Failed to disconnect wallet"; - setState((prev) => ({ - ...prev, - error: errorMessage, - })); - } - }, []); - - const clearError = useCallback(() => { - setState((prev) => ({ ...prev, error: null })); - }, []); - - return { - ...state, - connect, - disconnect, - clearError, - }; -} \ No newline at end of file diff --git a/veilend-web/src/lib/api/dashboard.ts b/veilend-web/src/lib/api/dashboard.ts deleted file mode 100644 index accdd26..0000000 --- a/veilend-web/src/lib/api/dashboard.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { DashboardData, ActivityActionType, AssetBalance } from '../types/dashboard'; - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; - -// For the demo/campaign, we can use a hardcoded or random dummy address if none is provided. -// In a real app with wallet connect, this would be passed dynamically. -const DEMO_ADDRESS = 'GCOQ4Z...'; // example stellar pubkey - -// Define types for API responses -interface IndexerPosition { - assetAddress: string; - depositedAmount: string | number; - borrowedAmount: string | number; -} - -interface IndexerTransaction { - id: string; - type: string; - amount: string | number; - assetAddress: string; - timestamp: string; - txHash: string; -} - -export async function fetchDashboardData(address: string = DEMO_ADDRESS): Promise { - try { - const [positionsRes, transactionsRes] = await Promise.all([ - fetch(`${API_BASE_URL}/indexer/positions/${address}`, { next: { revalidate: 10 } }), - fetch(`${API_BASE_URL}/indexer/transactions/${address}`, { next: { revalidate: 10 } }) - ]); - - if (!positionsRes.ok || !transactionsRes.ok) { - throw new Error('Failed to fetch data from live indexer endpoints'); - } - - const { positions } = await positionsRes.json() as { positions: IndexerPosition[] }; - const { transactions } = await transactionsRes.json() as { transactions: IndexerTransaction[] }; - - let totalDepositedUsd = 0; - let totalBorrowedUsd = 0; - const depositedAssets: AssetBalance[] = []; - const borrowedAssets: AssetBalance[] = []; - - // Map positions (assuming naive 1:1 USD pricing for demo unless oracle is integrated) - // The backend returns IndexerPosition: { assetAddress, depositedAmount, borrowedAmount } - if (Array.isArray(positions)) { - positions.forEach((pos: IndexerPosition) => { - const deposited = Number(pos.depositedAmount) / 1e7; // Assuming 7 decimals (Stellar standard) - const borrowed = Number(pos.borrowedAmount) / 1e7; - - // Mock price for demo since Oracle might not be fully wired in the read models yet - const price = pos.assetAddress.includes('USDC') ? 1.0 : 0.11; // Dummy XLM price - - if (deposited > 0) { - const usdValue = deposited * price; - totalDepositedUsd += usdValue; - depositedAssets.push({ - assetSymbol: pos.assetAddress.substring(0, 4), // Dummy symbol from address - assetName: pos.assetAddress, - balance: deposited, - usdValue, - }); - } - - if (borrowed > 0) { - const usdValue = borrowed * price; - totalBorrowedUsd += usdValue; - borrowedAssets.push({ - assetSymbol: pos.assetAddress.substring(0, 4), - assetName: pos.assetAddress, - balance: borrowed, - usdValue, - }); - } - }); - } - - const healthFactor = totalBorrowedUsd === 0 ? 99.99 : (totalDepositedUsd * 0.8) / totalBorrowedUsd; // Assumed 80% LTV - const totalBalanceUsd = totalDepositedUsd - totalBorrowedUsd; - - // Map transactions - const recentActivity = Array.isArray(transactions) ? transactions.map((tx: IndexerTransaction) => { - const amount = Number(tx.amount) / 1e7; - const price = tx.assetAddress.includes('USDC') ? 1.0 : 0.11; - return { - id: tx.id, - action: tx.type.toUpperCase() as ActivityActionType, - assetSymbol: tx.assetAddress.substring(0, 4), - amount, - usdValue: amount * price, - timestamp: tx.timestamp, - status: 'COMPLETED' as const, - txHash: tx.txHash, - }; - }).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()) : []; - - return { - portfolio: { - totalBalanceUsd, - healthFactor, - totalDepositedUsd, - totalBorrowedUsd, - depositedAssets, - borrowedAssets, - lastUpdated: new Date().toISOString(), - }, - recentActivity, - }; - } catch (error) { - console.error('API Error:', error); - throw new Error('Could not load live dashboard data. Is the NestJS indexer running?'); - } -} \ No newline at end of file diff --git a/veilend-web/src/lib/campaignAnalytics.ts b/veilend-web/src/lib/campaignAnalytics.ts deleted file mode 100644 index b257fba..0000000 --- a/veilend-web/src/lib/campaignAnalytics.ts +++ /dev/null @@ -1,57 +0,0 @@ -export type CampaignEventName = - | 'campaign_page_visit' - | 'campaign_cta_click' - | 'campaign_contributor_interest'; - -export type CampaignEventPayload = { - path?: string; - referrer?: string; - source?: string; - ctaId?: string; - ctaLabel?: string; - targetUrl?: string; - interestArea?: string; -}; - -export type CampaignEvent = { - event: CampaignEventName; - campaign: 'grantfox-oss-stellar'; - timestamp: string; - payload: CampaignEventPayload; -}; - -const ANALYTICS_ENDPOINT = '/api/campaign-events'; - -export function trackCampaignEvent(event: CampaignEventName, payload: CampaignEventPayload = {}) { - if (typeof window === 'undefined') { - return; - } - - const body: CampaignEvent = { - event, - campaign: 'grantfox-oss-stellar', - timestamp: new Date().toISOString(), - payload: { - path: window.location.pathname, - source: new URLSearchParams(window.location.search).get('utm_source') ?? undefined, - ...payload, - }, - }; - - const serializedBody = JSON.stringify(body); - - if (navigator.sendBeacon) { - const blob = new Blob([serializedBody], { type: 'application/json' }); - navigator.sendBeacon(ANALYTICS_ENDPOINT, blob); - return; - } - - fetch(ANALYTICS_ENDPOINT, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: serializedBody, - keepalive: true, - }).catch(() => undefined); -} diff --git a/veilend-web/src/lib/config-validation.ts b/veilend-web/src/lib/config-validation.ts deleted file mode 100644 index 4948cef..0000000 --- a/veilend-web/src/lib/config-validation.ts +++ /dev/null @@ -1,173 +0,0 @@ -/** - * Startup configuration validation for VeilLend Web. - * - * Call `validateConfig()` once at build/startup time (e.g. from next.config.ts) - * so that missing or invalid environment variables are surfaced immediately - * with a clear, actionable error rather than a cryptic runtime failure. - * - * All four variables have safe defaults for local development on testnet, so - * the app can start without any `.env.local` file. Explicit values are only - * required when deploying to mainnet or a custom network. - */ - -// ─── Types ──────────────────────────────────────────────────────────────────── - -/** The set of validated, typed config values available at runtime. */ -export interface AppConfig { - stellarNetwork: "testnet" | "mainnet" | "futurenet"; - horizonUrl: string; - networkPassphrase: string; - apiUrl: string; -} - -/** A single validation failure. */ -interface ValidationError { - variable: string; - value: string | undefined; - message: string; -} - -// ─── Constants ──────────────────────────────────────────────────────────────── - -const VALID_NETWORKS = ["testnet", "mainnet", "futurenet"] as const; -type StellarNetwork = (typeof VALID_NETWORKS)[number]; - -const DEFAULTS: Record = { - NEXT_PUBLIC_STELLAR_NETWORK: "testnet", - NEXT_PUBLIC_HORIZON_URL: "https://horizon-testnet.stellar.org", - NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE: "Test SDF Network ; September 2015", - NEXT_PUBLIC_API_URL: "http://localhost:3001", -}; - -// ─── Validators ─────────────────────────────────────────────────────────────── - -function isValidUrl(value: string): boolean { - try { - const url = new URL(value); - return url.protocol === "http:" || url.protocol === "https:"; - } catch { - return false; - } -} - -function isValidStellarNetwork(value: string): value is StellarNetwork { - return (VALID_NETWORKS as readonly string[]).includes(value); -} - -// ─── Core validation ────────────────────────────────────────────────────────── - -/** - * Resolve an env var, falling back to the built-in default when the variable - * is absent or empty. - */ -function resolve(key: string): string { - const raw = process.env[key]; - return (raw && raw.trim()) ? raw.trim() : (DEFAULTS[key] ?? ""); -} - -/** - * Validate all environment variables and return a typed `AppConfig`. - * - * Throws a single, formatted error listing every problem found so contributors - * can fix all issues in one go rather than discovering them one by one. - */ -export function validateConfig(): AppConfig { - const errors: ValidationError[] = []; - - // ── NEXT_PUBLIC_STELLAR_NETWORK ──────────────────────────────────────────── - const stellarNetwork = resolve("NEXT_PUBLIC_STELLAR_NETWORK"); - - if (!isValidStellarNetwork(stellarNetwork)) { - errors.push({ - variable: "NEXT_PUBLIC_STELLAR_NETWORK", - value: stellarNetwork, - message: `Must be one of: ${VALID_NETWORKS.join(", ")}. Got: "${stellarNetwork}"`, - }); - } - - // ── NEXT_PUBLIC_HORIZON_URL ──────────────────────────────────────────────── - const horizonUrl = resolve("NEXT_PUBLIC_HORIZON_URL"); - - if (!isValidUrl(horizonUrl)) { - errors.push({ - variable: "NEXT_PUBLIC_HORIZON_URL", - value: horizonUrl, - message: `Must be a valid http/https URL. Got: "${horizonUrl}"`, - }); - } - - // ── NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE ───────────────────────────────── - const networkPassphrase = resolve("NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE"); - - if (!networkPassphrase) { - errors.push({ - variable: "NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE", - value: networkPassphrase, - message: "Must not be empty.", - }); - } - - // ── NEXT_PUBLIC_API_URL ──────────────────────────────────────────────────── - const apiUrl = resolve("NEXT_PUBLIC_API_URL"); - - if (!isValidUrl(apiUrl)) { - errors.push({ - variable: "NEXT_PUBLIC_API_URL", - value: apiUrl, - message: `Must be a valid http/https URL. Got: "${apiUrl}"`, - }); - } - - // ── Report all errors at once ────────────────────────────────────────────── - if (errors.length > 0) { - const lines = [ - "", - "╔══════════════════════════════════════════════════════════╗", - "║ VeilLend — invalid or missing environment variables ║", - "╚══════════════════════════════════════════════════════════╝", - "", - "The following configuration problems were detected:", - "", - ...errors.map( - (e, i) => - ` ${i + 1}. ${e.variable}\n → ${e.message}`, - ), - "", - "Fix these values in .env.local (copy .env.example to get started):", - "", - " cp .env.example .env.local", - "", - "See veilend-web/README.md § Environment Variables for full documentation.", - "", - ]; - - throw new Error(lines.join("\n")); - } - - // ── Return typed config ──────────────────────────────────────────────────── - return { - stellarNetwork: stellarNetwork as StellarNetwork, - horizonUrl, - networkPassphrase, - apiUrl, - }; -} - -/** - * Cached, validated configuration. - * - * Import this anywhere in the codebase to access config values with the - * guarantee that they have already passed validation at startup. - * - * NOTE: This is evaluated at module-load time on the server (during - * `next build` / `next start`). On the client side Next.js inlines - * NEXT_PUBLIC_ values at build time, so no validation is needed there. - */ -let _config: AppConfig | undefined; - -export function getConfig(): AppConfig { - if (!_config) { - _config = validateConfig(); - } - return _config; -} diff --git a/veilend-web/src/lib/hooks/usePositionSync.ts b/veilend-web/src/lib/hooks/usePositionSync.ts deleted file mode 100644 index 4c7d473..0000000 --- a/veilend-web/src/lib/hooks/usePositionSync.ts +++ /dev/null @@ -1,124 +0,0 @@ -'use client' - -import * as React from 'react'; -import { DashboardData } from '@/lib/types/dashboard'; -import { fetchDashboardData } from '@/lib/api/dashboard'; - -/** Discrete sync states the UI can branch on. */ -export type SyncStatus = 'idle' | 'loading' | 'live' | 'stale' | 'empty' | 'error'; - -export interface PositionSyncState { - status: SyncStatus; - data: DashboardData | null; - /** When the data was last successfully refreshed (ms epoch), null until first load */ - lastSyncedAt: number | null; - error: string | null; - /** Manually trigger a refresh */ - refresh: () => void; -} - -interface UsePositionSyncOptions { - address?: string; - /** Poll interval in ms (default 10s, matching the indexer revalidate window) */ - intervalMs?: number; - /** How long before data is considered stale and flagged in the UI (default 30s) */ - staleAfterMs?: number; - /** Pause polling (e.g. when the tab is hidden or wallet disconnected) */ - enabled?: boolean; -} - -/** - * Keeps positions, collateral and borrowed values in sync with live protocol - * state by polling the indexer. Exposes explicit loading / empty / stale / error - * states so the dashboard can represent each clearly. Privacy mode is orthogonal: - * this hook only manages the values; masking is handled at render time. - */ -export function usePositionSync( - options: UsePositionSyncOptions = {}, -): PositionSyncState { - const { - address, - intervalMs = 10_000, - staleAfterMs = 30_000, - enabled = true, - } = options; - - const [data, setData] = React.useState(null); - const [status, setStatus] = React.useState('idle'); - const [lastSyncedAt, setLastSyncedAt] = React.useState(null); - const [error, setError] = React.useState(null); - - // Guards against state updates after unmount / overlapping requests - const inFlight = React.useRef(false); - const mounted = React.useRef(true); - - const load = React.useCallback(async () => { - if (inFlight.current) return; - inFlight.current = true; - - // Only show the full loading state on the very first fetch; subsequent - // polls refresh in the background without flickering the UI. - setStatus((prev) => (prev === 'idle' ? 'loading' : prev)); - - try { - const result = await fetchDashboardData(address); - if (!mounted.current) return; - - const isEmpty = - result.portfolio.depositedAssets.length === 0 && - result.portfolio.borrowedAssets.length === 0 && - result.recentActivity.length === 0; - - setData(result); - setLastSyncedAt(Date.now()); - setError(null); - setStatus(isEmpty ? 'empty' : 'live'); - } catch (err) { - if (!mounted.current) return; - setError(err instanceof Error ? err.message : 'Failed to sync positions.'); - // Keep stale data visible if we have it; otherwise surface the error. - setStatus(data ? 'stale' : 'error'); - } finally { - inFlight.current = false; - } - }, [address, data]); - - // Initial load + interval polling - React.useEffect(() => { - mounted.current = true; - if (!enabled) return; - - // Intentional fetch-on-mount: load() flips status to 'loading' before the - // first await, which the rule flags; that initial transition is the point. - // eslint-disable-next-line react-hooks/set-state-in-effect - load(); - const id = setInterval(load, intervalMs); - return () => { - mounted.current = false; - clearInterval(id); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [enabled, intervalMs, address]); - - // Independent staleness ticker: flags data as stale if a poll hasn't - // succeeded within staleAfterMs, even while requests keep failing. - React.useEffect(() => { - if (lastSyncedAt === null) return; - const id = setInterval(() => { - if (!mounted.current) return; - setStatus((prev) => { - if (prev !== 'live' && prev !== 'empty') return prev; - return Date.now() - lastSyncedAt > staleAfterMs ? 'stale' : prev; - }); - }, Math.min(staleAfterMs, 5_000)); - return () => clearInterval(id); - }, [lastSyncedAt, staleAfterMs]); - - return { - status, - data, - lastSyncedAt, - error, - refresh: load, - }; -} diff --git a/veilend-web/src/lib/stellar/auth.ts b/veilend-web/src/lib/stellar/auth.ts deleted file mode 100644 index 5fb9fdd..0000000 --- a/veilend-web/src/lib/stellar/auth.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Stellar wallet authentication utilities - * Handles wallet-driven sign-in with signature verification - */ - -import { Keypair } from "@stellar/stellar-sdk"; - -const AUTH_STORAGE_KEY = "veillend_auth"; -const WALLET_ADDRESS_KEY = "veillend_wallet_address"; - -export interface AuthSession { - address: string; - publicKey: string; - authenticated: boolean; - sessionId?: string; - expiresAt?: string; -} - -/** - * Generate a challenge message for wallet authentication - */ -export const generateChallenge = (address: string): string => { - const timestamp = Date.now(); - const nonce = Math.random().toString(36).substring(2, 15); - return `VeilLend authentication\nAddress: ${address}\nNonce: ${nonce}\nTimestamp: ${timestamp}`; -}; - -/** - * Check if a wallet is authenticated - */ -export const isWalletAuthenticated = (): boolean => { - if (typeof window === "undefined") return false; - - try { - const authData = localStorage.getItem(AUTH_STORAGE_KEY); - if (!authData) return false; - - const session = JSON.parse(authData) as AuthSession; - if (!session.authenticated) return false; - - // Check if session has expired - if (session.expiresAt) { - const expiresAt = new Date(session.expiresAt); - if (expiresAt < new Date()) { - // Session expired - localStorage.removeItem(AUTH_STORAGE_KEY); - return false; - } - } - - return true; - } catch { - return false; - } -}; - -/** - * Get the authenticated wallet address - */ -export const getAuthenticatedWallet = (): string | null => { - if (typeof window === "undefined") return null; - - try { - return localStorage.getItem(WALLET_ADDRESS_KEY); - } catch { - return null; - } -}; - -/** - * Create a new auth session - */ -export const createAuthSession = (address: string, publicKey: string): AuthSession => { - const session: AuthSession = { - address, - publicKey, - authenticated: true, - sessionId: crypto.randomUUID ? crypto.randomUUID() : `session_${Date.now()}_${Math.random()}`, - expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // 24 hours - }; - - if (typeof window !== "undefined") { - localStorage.setItem(AUTH_STORAGE_KEY, JSON.stringify(session)); - localStorage.setItem(WALLET_ADDRESS_KEY, address); - } - - return session; -}; - -/** - * Clear the auth session (logout) - */ -export const clearAuthSession = (): void => { - if (typeof window !== "undefined") { - localStorage.removeItem(AUTH_STORAGE_KEY); - localStorage.removeItem(WALLET_ADDRESS_KEY); - } -}; - -/** - * Validate a wallet address format - */ -export const isValidStellarAddress = (address: string): boolean => { - try { - Keypair.fromPublicKey(address); - return true; - } catch { - return false; - } -}; \ No newline at end of file diff --git a/veilend-web/src/lib/stellar/config.ts b/veilend-web/src/lib/stellar/config.ts deleted file mode 100644 index 4c9306b..0000000 --- a/veilend-web/src/lib/stellar/config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Stellar network configuration for VeilLend - */ - -export const STELLAR_CONFIG = { - network: process.env.NEXT_PUBLIC_STELLAR_NETWORK || "testnet", - horizonUrl: process.env.NEXT_PUBLIC_HORIZON_URL || "https://horizon-testnet.stellar.org", - networkPassphrase: process.env.NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE || "Test SDF Network ; September 2015", - appName: "VeilLend", -}; - -export const getHorizonUrl = (): string => { - return STELLAR_CONFIG.horizonUrl; -}; - -export const getNetworkPassphrase = (): string => { - return STELLAR_CONFIG.networkPassphrase; -}; - -export const isTestnet = (): boolean => { - return STELLAR_CONFIG.network === "testnet"; -}; \ No newline at end of file diff --git a/veilend-web/src/lib/stellar/wallet.ts b/veilend-web/src/lib/stellar/wallet.ts deleted file mode 100644 index c02883f..0000000 --- a/veilend-web/src/lib/stellar/wallet.ts +++ /dev/null @@ -1,175 +0,0 @@ -/** - * Stellar wallet connection utilities - * Supports Freighter wallet integration - */ - -import { Horizon, TransactionBuilder, Operation, Keypair } from "@stellar/stellar-sdk"; -import { isConnected, getAddress, signTransaction } from "@stellar/freighter-api"; -import { getHorizonUrl, getNetworkPassphrase } from "./config"; - -export interface WalletInfo { - address: string; - publicKey: string; -} - -/** - * Check if Freighter wallet is installed - */ -export const isFreighterInstalled = (): boolean => { - if (typeof window === "undefined") return false; - return !!(window as Window & { freighter?: unknown }).freighter; -}; - -/** - * Connect to Freighter wallet - */ -export const connectFreighter = async (): Promise => { - if (!isFreighterInstalled()) { - throw new Error("Freighter wallet is not installed. Please install Freighter from https://www.freighter.app/"); - } - - try { - const isConnectedResult = await isConnected(); - if (!isConnectedResult.isConnected) { - throw new Error("Freighter is not connected. Please unlock your wallet."); - } - - const addressResult = await getAddress(); - if (!addressResult || typeof addressResult !== 'object' || !('address' in addressResult)) { - throw new Error("Failed to get address from Freighter."); - } - - const publicKey = addressResult.address; - if (!publicKey) { - throw new Error("Failed to get public key from Freighter."); - } - - return { - address: publicKey, - publicKey: publicKey, - }; - } catch (error) { - console.error("Freighter connection error:", error); - throw new Error(error instanceof Error ? error.message : "Failed to connect to Freighter wallet."); - } -}; - -/** - * Get Freighter wallet address - */ -export const getFreighterAddress = async (): Promise => { - if (!isFreighterInstalled()) { - throw new Error("Freighter wallet is not installed."); - } - - try { - const addressResult = await getAddress(); - if (!addressResult || typeof addressResult !== 'object' || !('address' in addressResult)) { - throw new Error("Failed to get address from Freighter."); - } - - const address = addressResult.address; - if (!address) { - throw new Error("Failed to get address from Freighter."); - } - - return address; - } catch (error) { - console.error("Get address error:", error); - throw new Error(error instanceof Error ? error.message : "Failed to get address."); - } -}; - -/** - * Sign a message using Freighter wallet - */ -export const signMessage = async (message: string): Promise => { - if (!isFreighterInstalled()) { - throw new Error("Freighter wallet is not installed."); - } - - try { - const addressResult = await getAddress(); - if (!addressResult || typeof addressResult !== 'object' || !('address' in addressResult)) { - throw new Error("Failed to get address from Freighter."); - } - - const publicKey = addressResult.address; - if (!publicKey) { - throw new Error("Failed to get public key."); - } - - const server = new Horizon.Server(getHorizonUrl()); - let account: Horizon.AccountResponse; - - try { - account = await server.loadAccount(publicKey); - } catch { - // Account might not exist on testnet, use a dummy account for signing - account = { - accountId: publicKey, - sequenceNumber: "0", - incrementSequenceNumber: () => {}, - signers: [], - thresholds: { low: 0, medium: 0, high: 0 }, - _baseFee: () => 100, - _networkId: Buffer.alloc(32), - } as unknown as Horizon.AccountResponse; - } - - // Create a dummy transaction for signing - const tx = new TransactionBuilder(account, { - fee: "100", - networkPassphrase: getNetworkPassphrase(), - }) - .addOperation(Operation.setOptions({})) - .setTimeout(30) - .build(); - - const txXdr = tx.toXDR(); - const signedTx = await signTransaction(txXdr, { - networkPassphrase: getNetworkPassphrase(), - }); - - // Return the signed transaction XDR - if (typeof signedTx === 'string') { - return signedTx; - } - - if (signedTx && typeof signedTx === 'object' && 'signedTxXdr' in signedTx) { - const signedTxObj = signedTx as { signedTxXdr: string }; - return signedTxObj.signedTxXdr; - } - - return `signed_${message.substring(0, 20)}_${Date.now()}`; - } catch (error) { - console.error("Message signing error:", error); - throw new Error(error instanceof Error ? error.message : "Failed to sign message."); - } -}; - -/** - * Verify a signed message - */ -export const verifySignedMessage = async ( - _message: string, - _signature: string, - publicKey: string -): Promise => { - try { - const keypair = Keypair.fromPublicKey(publicKey); - return keypair.publicKey() === publicKey; - } catch { - return false; - } -}; - -/** - * Disconnect wallet (clears local state) - */ -export const disconnectWallet = async (): Promise => { - if (typeof window !== "undefined") { - localStorage.removeItem("veillend_wallet_address"); - localStorage.removeItem("veillend_wallet_auth"); - } -}; \ No newline at end of file diff --git a/veilend-web/src/lib/types/dashboard.ts b/veilend-web/src/lib/types/dashboard.ts deleted file mode 100644 index a8afb89..0000000 --- a/veilend-web/src/lib/types/dashboard.ts +++ /dev/null @@ -1,34 +0,0 @@ -export interface AssetBalance { - assetSymbol: string; - assetName: string; - balance: number; - usdValue: number; -} - -export interface PortfolioData { - totalBalanceUsd: number; - healthFactor: number; - totalDepositedUsd: number; - totalBorrowedUsd: number; - depositedAssets: AssetBalance[]; - borrowedAssets: AssetBalance[]; - lastUpdated: string; // ISO timestamp -} - -export type ActivityActionType = 'DEPOSIT' | 'BORROW' | 'REPAY' | 'WITHDRAW'; - -export interface ActivityEvent { - id: string; - action: ActivityActionType; - assetSymbol: string; - amount: number; - usdValue: number; - timestamp: string; // ISO timestamp - status: 'PENDING' | 'COMPLETED' | 'FAILED'; - txHash?: string; -} - -export interface DashboardData { - portfolio: PortfolioData; - recentActivity: ActivityEvent[]; -} diff --git a/veilend-web/src/lib/utils.ts b/veilend-web/src/lib/utils.ts deleted file mode 100644 index bd0c391..0000000 --- a/veilend-web/src/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) -} diff --git a/veilend-web/src/lib/validation/amount.test.ts b/veilend-web/src/lib/validation/amount.test.ts deleted file mode 100644 index 85d152b..0000000 --- a/veilend-web/src/lib/validation/amount.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { - parseAmount, - exceedsPrecision, - validateAmount, - ValidationContext, -} from './amount'; - -const baseCtx: ValidationContext = { - availableBalance: 1000, - priceUsd: 1, - decimals: 7, -}; - -describe('parseAmount', () => { - it('parses clean decimals', () => { - expect(parseAmount('12.5')).toBe(12.5); - expect(parseAmount(' 100 ')).toBe(100); - expect(parseAmount('0.0000001')).toBe(0.0000001); - }); - - it('rejects non-numeric and malformed input', () => { - expect(parseAmount('')).toBeNull(); - expect(parseAmount('abc')).toBeNull(); - expect(parseAmount('1.2.3')).toBeNull(); - expect(parseAmount('-5')).toBeNull(); - expect(parseAmount('1e5')).toBeNull(); - }); -}); - -describe('exceedsPrecision', () => { - it('accepts values within 7 decimals', () => { - expect(exceedsPrecision(1.1234567, 7)).toBe(false); - }); - it('rejects values beyond the asset precision', () => { - expect(exceedsPrecision(1.12345678, 7)).toBe(true); - }); -}); - -describe('validateAmount — common guards', () => { - it('blocks empty / zero / negative', () => { - expect(validateAmount('DEPOSIT', '', baseCtx).valid).toBe(false); - expect(validateAmount('DEPOSIT', '0', baseCtx).valid).toBe(false); - expect(validateAmount('DEPOSIT', '-1', baseCtx).valid).toBe(false); - }); - - it('blocks amounts exceeding precision', () => { - const r = validateAmount('DEPOSIT', '1.123456789', baseCtx); - expect(r.valid).toBe(false); - expect(r.message).toMatch(/decimal/i); - }); -}); - -describe('validateAmount — DEPOSIT/WITHDRAW', () => { - it('blocks amounts above balance', () => { - const r = validateAmount('DEPOSIT', '1001', baseCtx); - expect(r.valid).toBe(false); - expect(r.severity).toBe('error'); - }); - - it('warns when using the full balance', () => { - const r = validateAmount('WITHDRAW', '1000', baseCtx); - expect(r.valid).toBe(true); - expect(r.severity).toBe('warning'); - }); - - it('accepts a normal amount', () => { - expect(validateAmount('DEPOSIT', '500', baseCtx)).toEqual({ valid: true }); - }); -}); - -describe('validateAmount — BORROW', () => { - const ctx: ValidationContext = { ...baseCtx, borrowLimitUsd: 100, priceUsd: 1 }; - - it('blocks borrowing above the limit', () => { - const r = validateAmount('BORROW', '101', ctx); - expect(r.valid).toBe(false); - expect(r.message).toMatch(/borrow limit/i); - }); - - it('warns when borrowing near the limit', () => { - const r = validateAmount('BORROW', '85', ctx); - expect(r.valid).toBe(true); - expect(r.severity).toBe('warning'); - expect(r.message).toMatch(/liquidation/i); - }); - - it('accepts a safe borrow', () => { - expect(validateAmount('BORROW', '50', ctx)).toEqual({ valid: true }); - }); -}); - -describe('validateAmount — REPAY', () => { - const ctx: ValidationContext = { ...baseCtx, outstandingDebt: 200, availableBalance: 1000 }; - - it('blocks repaying more than owed', () => { - const r = validateAmount('REPAY', '201', ctx); - expect(r.valid).toBe(false); - expect(r.message).toMatch(/owe/i); - }); - - it('blocks repaying more than balance', () => { - const lowBal: ValidationContext = { ...ctx, outstandingDebt: 5000, availableBalance: 100 }; - const r = validateAmount('REPAY', '150', lowBal); - expect(r.valid).toBe(false); - expect(r.message).toMatch(/balance/i); - }); - - it('accepts a valid partial repay', () => { - expect(validateAmount('REPAY', '100', ctx)).toEqual({ valid: true }); - }); -}); diff --git a/veilend-web/src/lib/validation/amount.ts b/veilend-web/src/lib/validation/amount.ts deleted file mode 100644 index 88c49bf..0000000 --- a/veilend-web/src/lib/validation/amount.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { ActivityActionType } from '../types/dashboard'; - -export interface ValidationContext { - /** User's available balance of the asset, in human units (not raw) */ - availableBalance: number; - /** For BORROW: remaining borrow capacity in USD; for REPAY: outstanding debt */ - borrowLimitUsd?: number; - /** Current outstanding debt for the asset, in human units */ - outstandingDebt?: number; - /** Price of the asset in USD */ - priceUsd: number; - /** Decimals of the asset (Stellar standard is 7) */ - decimals?: number; -} - -export type ValidationSeverity = 'error' | 'warning'; - -export interface ValidationResult { - valid: boolean; - severity?: ValidationSeverity; - /** Short, mobile-friendly message */ - message?: string; -} - -const OK: ValidationResult = { valid: true }; - -/** - * Parse a raw user input string into a number, rejecting anything that is not a - * clean positive decimal. Returns null when unparseable. - */ -export function parseAmount(input: string): number | null { - const trimmed = input.trim(); - if (trimmed === '') return null; - // Only digits and at most one decimal point - if (!/^\d*\.?\d*$/.test(trimmed)) return null; - const value = Number(trimmed); - if (!Number.isFinite(value)) return null; - return value; -} - -/** - * Enforce that an amount does not exceed the asset's decimal precision. - * Stellar assets use 7 decimals — more than that cannot be represented on-chain. - */ -export function exceedsPrecision(value: number, decimals = 7): boolean { - const factor = 10 ** decimals; - const scaled = value * factor; - return Math.abs(scaled - Math.round(scaled)) > 1e-6; -} - -/** - * Validate a deposit/borrow/repay/withdraw amount against the user's context. - * Returns the first blocking error, or a non-blocking warning, or OK. - */ -export function validateAmount( - action: ActivityActionType, - input: string, - ctx: ValidationContext, -): ValidationResult { - const value = parseAmount(input); - - if (value === null) { - return { valid: false, severity: 'error', message: 'Enter a valid amount.' }; - } - if (value <= 0) { - return { valid: false, severity: 'error', message: 'Amount must be greater than zero.' }; - } - if (exceedsPrecision(value, ctx.decimals ?? 7)) { - return { - valid: false, - severity: 'error', - message: `Max ${ctx.decimals ?? 7} decimal places.`, - }; - } - - switch (action) { - case 'DEPOSIT': - case 'WITHDRAW': { - if (value > ctx.availableBalance) { - return { - valid: false, - severity: 'error', - message: `Exceeds your balance of ${formatShort(ctx.availableBalance)}.`, - }; - } - // Warn if using the entire balance (no buffer left for fees) - if (value === ctx.availableBalance) { - return { - valid: true, - severity: 'warning', - message: 'Using your full balance leaves nothing for network fees.', - }; - } - return OK; - } - - case 'BORROW': { - const usd = value * ctx.priceUsd; - if (ctx.borrowLimitUsd !== undefined && usd > ctx.borrowLimitUsd) { - return { - valid: false, - severity: 'error', - message: `Exceeds your borrow limit of $${formatShort(ctx.borrowLimitUsd)}.`, - }; - } - // Warn at >=80% of borrow limit — close to liquidation risk - if (ctx.borrowLimitUsd !== undefined && usd >= ctx.borrowLimitUsd * 0.8) { - return { - valid: true, - severity: 'warning', - message: 'Borrowing near your limit raises liquidation risk.', - }; - } - return OK; - } - - case 'REPAY': { - if (ctx.outstandingDebt !== undefined && value > ctx.outstandingDebt) { - return { - valid: false, - severity: 'error', - message: `You only owe ${formatShort(ctx.outstandingDebt)}.`, - }; - } - if (value > ctx.availableBalance) { - return { - valid: false, - severity: 'error', - message: `Exceeds your balance of ${formatShort(ctx.availableBalance)}.`, - }; - } - return OK; - } - - default: - return OK; - } -} - -function formatShort(n: number): string { - return new Intl.NumberFormat('en-US', { maximumFractionDigits: 4 }).format(n); -} diff --git a/veilend-web/tsconfig.json b/veilend-web/tsconfig.json deleted file mode 100644 index cf9c65d..0000000 --- a/veilend-web/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./src/*"] - } - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - ".next/dev/types/**/*.ts", - "**/*.mts" - ], - "exclude": ["node_modules"] -}