Alerts

Alerts & notifications system

Complete documentation for Torque's alerts & notifications system. Set up custom alerts for price movements, transactions, & portfolio changes.

Overview

Torque's alerts & notifications system allows users to receive email notifications for various events & activities. Users can configure which alerts they want to receive through the alerts settings page.

Configurable Alerts

Enable/disable specific alert types

Email Notifications

All alerts sent via email (Resend integration)

Real-Time Monitoring

Automatic monitoring for low balances, security events

Alert Preferences

Per-user alert preferences stored in database

Alert Types

Wallet Alerts

Low Balance Alerts (prevent-overdraft)

Notifies users when their wallet balance falls below a threshold.

Configuration:

  • Threshold: Default $10, configurable per user
  • Cooldown: 24 hours between alerts
  • Monitoring: Automatic, checks every 5 minutes

Payment Received (payment-received)

Notifies users when they receive a payment.

Reward Updates (reward-updates)

Notifies users about TORQ reward updates.

Trade Alerts

Trade Confirmations (swap-confirmations)

Notifies users when trades are confirmed on-chain.

High Slippage Warnings (slippage-alerts)

Warns users when a trade would result in high slippage.

Security Alerts

Security Alerts (security-alerts)

Notifies users about security-related events: wallet address changed, wallet disconnected, suspicious activity detected.

Market Alerts

Token Price Alerts (price-alerts)

Notifies users when watched tokens hit target prices. Supports both "above" & "below" thresholds.

Portfolio Alerts

Portfolio Value Alerts (portfolio-value-alerts)

Notifies users when portfolio value changes significantly. Configurable threshold percentage & direction.

Alert Configuration

User Preferences

user-preferences.ts
interface UserPreferences {
  alerts?: {
    "prevent-overdraft"?: boolean
    "swap-confirmations"?: boolean
    "slippage-alerts"?: boolean
    "security-alerts"?: boolean
    "reward-updates"?: boolean
    "payment-received"?: boolean
    "price-alerts"?: boolean
    "portfolio-value-alerts"?: boolean
  }
  alertsDestination?: "email" | "in-app" | "both"
  lowBalanceThreshold?: number // Default: 10
}

Alert Categories

Trade:Trade confirmations, slippage alerts
Wallet:Low balance, payment received, reward updates
Security:Security alerts
Market:Price alerts
Portfolio:Portfolio value alerts

API Integration

Send Alert

Endpoint: POST /api/alerts/send

send-alert.ts
const response = await fetch('/api/alerts/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    walletAddress: '0x...', // Optional
    recipientEmail: 'user@example.com', // Optional
    alertType: 'prevent-overdraft', // Required
    subject: 'Low Balance Alert', // Required
    message: 'Your wallet balance is running low.', // Optional (HTML supported)
    metadata: { // Optional
      balance: 5.50,
      threshold: 10.00,
      type: 'low_balance'
    }
  })
})

// Response: { success: true, emailId: "string" }

Error Responses

400- Missing required fields, invalid email, alert disabled, destination not set
404- User not found
500- Email service not configured, failed to send email

Business Notifications

Endpoint: POST /api/business/notify

business-notify.ts
const response = await fetch('/api/business/notify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    businessId: 'business_id', // Required
    alertType: 'order-confirmation', // Required
    subject: 'New Order Received', // Required
    message: 'You have received a new order.', // Required
    metadata: { // Optional
      orderId: 'order_123',
      amount: 10000
    }
  })
})

// Business Notification Types:
// - order-confirmation: New order received
// - payment-received: Payment received
// - order-status-update: Order status changed
// - low-inventory: Product inventory low

Automatic Monitoring

Low Balance Monitor

Monitors wallet balance every 5 minutes. Checks against user's low balance threshold. Sends alert when balance falls below threshold with 24-hour cooldown period.

low-balance-monitor.ts
// Automatic monitoring
useEffect(() => {
  const checkBalance = async () => {
    if (balance < lowBalanceThreshold && canSendAlert(address)) {
      await fetch('/api/alerts/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          walletAddress: address,
          alertType: 'prevent-overdraft',
          subject: 'Low Balance Alert',
          message: `Your wallet balance is running low.<br><br>Current Balance: $${balance.toFixed(2)}<br>Threshold: $${threshold.toFixed(2)}`,
          metadata: {
            balance,
            threshold: lowBalanceThreshold,
            type: 'low_balance'
          }
        })
      })
    }
  }
  
  checkBalance()
  const interval = setInterval(checkBalance, 5 * 60 * 1000) // 5 minutes
  return () => clearInterval(interval)
}, [balance, lowBalanceThreshold])

Security Monitor

Monitors wallet connection state. Detects wallet address changes & disconnections. Sends security alerts automatically.

security-monitor.ts
useEffect(() => {
  if (isConnected && address) {
    if (lastAddress && lastAddress !== address) {
      // Address changed - send alert
      fetch('/api/alerts/send', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          walletAddress: address,
          alertType: 'security-alerts',
          subject: 'Wallet Address Changed',
          message: `Your connected wallet address has changed.<br><br>Previous: ${lastAddress}<br>Current: ${address}`,
          metadata: {
            previousAddress: lastAddress,
            currentAddress: address,
            type: 'address_change'
          }
        })
      })
    }
  }
}, [address, isConnected])

Alert Preferences Management

User Interface

Route: /alerts

Features: Toggle alerts on/off, category filtering, real-time preference updates, visual feedback

API Integration

preferences-management.ts
// Update preferences
await updateUserPreferences({
  walletAddress: address,
  preferences: {
    alerts: {
      "prevent-overdraft": true,
      "swap-confirmations": false,
      "slippage-alerts": true,
      "security-alerts": true,
      "reward-updates": false,
      "payment-received": true,
      "price-alerts": false,
      "portfolio-value-alerts": false
    },
    lowBalanceThreshold: 20, // $20
    alertsDestination: "email"
  }
})

// Get preferences
const user = await getUserByWallet({ walletAddress: address })
const alerts = user.preferences?.alerts
const threshold = user.preferences?.lowBalanceThreshold

Examples

Sending Low Balance Alert

low-balance-alert.ts
const checkBalance = async () => {
  if (balance < threshold && canSendAlert(address)) {
    const response = await fetch('/api/alerts/send', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        walletAddress: address,
        alertType: 'prevent-overdraft',
        subject: 'Low Balance Alert',
        message: `Your wallet balance is running low.<br><br>Current Balance: $${balance.toFixed(2)}<br>Threshold: $${threshold.toFixed(2)}<br>Please add funds to avoid failed transactions.`,
        metadata: {
          balance,
          threshold,
          type: 'low_balance'
        }
      })
    })
  }
}

Sending Trade Confirmation

trade-confirmation-alert.ts
// After trade transaction confirms
await fetch('/api/alerts/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    walletAddress: address,
    alertType: 'swap-confirmations',
    subject: 'Trade Confirmed',
    message: `Your trade has been confirmed.<br><br>Token In: ${amountIn} ${tokenIn}<br>Token Out: ${amountOut} ${tokenOut}<br>Transaction: ${txHash}`,
    metadata: {
      tokenIn,
      tokenOut,
      amountIn,
      amountOut,
      txHash,
      chainId
    }
  })
})

Sending Security Alert

security-alert.ts
// On wallet address change
await fetch('/api/alerts/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    walletAddress: newAddress,
    alertType: 'security-alerts',
    subject: 'Wallet Address Changed',
    message: `Your connected wallet address has changed.<br><br>Previous: ${oldAddress}<br>Current: ${newAddress}<br><br>If you did not make this change, please secure your account immediately.`,
    metadata: {
      previousAddress: oldAddress,
      currentAddress: newAddress,
      type: 'address_change'
    }
  })
})

Configuration

Environment Variables

# Resend Configuration
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL=alerts@torque.fi

# Convex Configuration
NEXT_PUBLIC_CONVEX_URL=https://...

Default Settings

  • Low Balance Threshold: $10
  • Alert Cooldown: 24 hours
  • Check Interval: 5 minutes
  • Email Provider: Resend
  • From Email: alerts@torque.fi

Troubleshooting

Alerts Not Sending

Problem: Alerts not being sent
Solution: Check RESEND_API_KEY is configured, verify user email is set, check alert is enabled in preferences, verify alert destination is set to email

Too Many Alerts

Problem: Receiving too many alerts
Solution: Adjust cooldown period, increase threshold values, disable specific alert types

Email Not Received

Problem: Email not received
Solution: Check spam folder, verify email address is correct, check Resend delivery logs, verify email domain is verified in Resend

Best Practices

  • Cooldown Periods: Always implement cooldown periods to prevent spam
  • User Preferences: Always check user preferences before sending
  • Error Handling: Handle email sending errors gracefully
  • Logging: Log all alert attempts for debugging
  • Testing: Test alerts in development before production
Was this helpful?