From 8c74bf26d544970d1d822a908e457628da032715 Mon Sep 17 00:00:00 2001 From: Sikkra <159844544+Sikkra@users.noreply.github.com> Date: Tue, 19 May 2026 11:09:29 -0500 Subject: [PATCH] Add health factor alert thresholds --- alerts/package-lock.json | 8 +++ alerts/package.json | 5 +- alerts/src/email.ts | 53 +++++++++++++- alerts/src/index.ts | 150 ++++++++++++++++++++++++++------------- alerts/src/schema.sql | 5 ++ alerts/src/stellar.ts | 26 +++---- alerts/tsconfig.json | 1 + frontend/index.html | 9 ++- frontend/src/main.ts | 8 +++ 9 files changed, 198 insertions(+), 67 deletions(-) diff --git a/alerts/package-lock.json b/alerts/package-lock.json index e8df802..7f205ac 100644 --- a/alerts/package-lock.json +++ b/alerts/package-lock.json @@ -8,6 +8,7 @@ "name": "turbolong-alerts", "version": "1.0.0", "devDependencies": { + "@cloudflare/workers-types": "^4.20260519.1", "typescript": "^5.7.3", "wrangler": "^3.99.0" } @@ -126,6 +127,13 @@ "node": ">=16" } }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20260519.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260519.1.tgz", + "integrity": "sha512-BMWAwg4RyyZn3zcdoXbqpfogm2DGfNb83DXNCM1oFUMhYtEX8I+B+oxf67YPKvSiAEbzd7nHzW2mLv3eBH8Etw==", + "dev": true, + "license": "MIT OR Apache-2.0" + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", diff --git a/alerts/package.json b/alerts/package.json index c57f47e..d87d6ff 100644 --- a/alerts/package.json +++ b/alerts/package.json @@ -9,7 +9,8 @@ "db:migrate": "wrangler d1 execute turbolong-alerts --file=src/schema.sql" }, "devDependencies": { - "wrangler": "^3.99.0", - "typescript": "^5.7.3" + "@cloudflare/workers-types": "^4.20260519.1", + "typescript": "^5.7.3", + "wrangler": "^3.99.0" } } diff --git a/alerts/src/email.ts b/alerts/src/email.ts index 3cf5c61..0a19a73 100644 --- a/alerts/src/email.ts +++ b/alerts/src/email.ts @@ -41,7 +41,7 @@ export async function sendVerificationEmail(env: Env, to: string, verifyUrl: str
Click the button below to verify your email and activate APY alerts.
+Click the button below to verify your email and activate APY and health-factor alerts.
Verify SubscriptionIf you didn't subscribe, ignore this email.
@@ -100,3 +100,54 @@ export async function sendApyAlert( html, ); } + +export async function sendHfAlert( + env: Env, + to: string, + opts: { + poolName: string; + assetSymbol: string; + leverage: number; + healthFactor: number; + threshold: number; + netApy: number; + unsubscribeUrl: string; + appUrl: string; + }, +): Promise${assetSymbol} at ${leverage}x on ${poolName}
+ +Current risk estimate
+| Health factor | ${healthFactor.toFixed(3)} |
| Alert threshold | ${threshold.toFixed(3)} |
| Net APY at ${leverage}x | ${netApy.toFixed(2)}% |
Your selected leverage bracket is below the health-factor threshold you chose. Consider reducing leverage or adding collateral.
+ + Open Turbolong + ++ Unsubscribe from this alert. +
+ +`.trim(); + + return sendEmail( + env, + to, + `Health Factor Alert: ${assetSymbol} at ${leverage}x on ${poolName}`, + html, + ); +} diff --git a/alerts/src/index.ts b/alerts/src/index.ts index 6b448ea..ceee1e2 100644 --- a/alerts/src/index.ts +++ b/alerts/src/index.ts @@ -10,8 +10,8 @@ * Fetch pool reserve rates, compute APY per bracket, alert subscribers. */ -import { POOLS, LEVERAGE_BRACKETS, POOL_NAMES, fetchReserveRates, computeNetApy, type ReserveRates } from "./stellar.ts"; -import { sendVerificationEmail, sendApyAlert } from "./email.ts"; +import { POOLS, LEVERAGE_BRACKETS, POOL_NAMES, fetchReserveRates, computeNetApy, computeHealthFactor, type ReserveRates } from "./stellar.ts"; +import { sendVerificationEmail, sendApyAlert, sendHfAlert } from "./email.ts"; interface Env { DB: D1Database; @@ -78,7 +78,7 @@ async function handleSubscribe(request: Request, env: Env): PromiseYou'll receive an alert when your position's net APY turns negative.
+You'll receive alerts when net APY turns negative or health factor crosses your threshold.