added rough mainnet implementation and added backup contact for email

This commit is contained in:
Siavash Sameni
2025-08-28 14:07:09 +04:00
parent 29c346e868
commit f60e4ca3a5
6 changed files with 86 additions and 18 deletions

14
.dockerignore Normal file
View File

@@ -0,0 +1,14 @@
node_modules
.next
.git
.gitignore
Dockerfile*
README.md
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.env*
.dockerignore
**/*.local.*
**/*.test.*
**/__tests__/**

41
Dockerfile Normal file
View File

@@ -0,0 +1,41 @@
# syntax=docker/dockerfile:1
# 1) Install dependencies
FROM --platform=linux/amd64 node:20-alpine AS deps
WORKDIR /app
ENV CI=true
# Install system deps commonly needed by Next.js
RUN apk add --no-cache libc6-compat
COPY package.json package-lock.json ./
RUN npm ci --legacy-peer-deps --no-audit --no-fund
# 2) Build the app
FROM --platform=linux/amd64 node:20-alpine AS builder
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Allow passing public env vars at build time
ARG NEXT_PUBLIC_NTFY_URL
ARG NEXT_PUBLIC_SCHEDY_URL
ENV NEXT_PUBLIC_NTFY_URL=${NEXT_PUBLIC_NTFY_URL:-/ntfy}
ENV NEXT_PUBLIC_SCHEDY_URL=${NEXT_PUBLIC_SCHEDY_URL:-/schedy}
RUN npm run build
# 3) Run with standalone output
FROM --platform=linux/amd64 node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Create non-root user
RUN adduser -D nextjs
# Copy the minimal standalone output
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/.next/BUILD_ID ./.next/BUILD_ID
# Expose and run
EXPOSE 3000
ENV PORT=3000 HOST=0.0.0.0
USER nextjs
CMD ["node", "server.js"]

View File

@@ -2,7 +2,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useAccount, useChainId, useReadContract, useReadContracts, useSwitchChain, usePublicClient, useWriteContract, useSendTransaction } from 'wagmi';
import { base, arbitrum } from 'wagmi/chains';
import { base, arbitrum, mainnet } from 'wagmi/chains';
import { Abi, parseUnits } from 'viem';
import debtAbi from '@/ABIs/mortgagefiusdccbbtcupgraded.json';
import Link from 'next/link';
@@ -21,6 +21,8 @@ const erc721Abi = [
{ type: 'function', name: 'tokenOfOwnerByIndex', stateMutability: 'view', inputs: [{ name: 'owner', type: 'address' }, { name: 'index', type: 'uint256' }], outputs: [{ type: 'uint256' }] },
] as const satisfies Abi;
const ENABLE_MAINNET = process.env.NEXT_PUBLIC_ENABLE_MAINNET === 'true';
const DEFAULTS = {
[base.id]: {
nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe',
@@ -30,10 +32,17 @@ const DEFAULTS = {
nft: '0xedE6F5F8A9D6B90b1392Dcc9E7FD8A5B0192Bfe1',
debt: '0x9Be2Cf73E62DD3b5dF4334D9A36888394822A33F',
},
...(ENABLE_MAINNET ? {
[mainnet.id]: {
// Dummy placeholders for future USDC-WETH mainnet vault
nft: '0x0000000000000000000000000000000000000001',
debt: '0x0000000000000000000000000000000000000002',
},
} : {}),
} as const;
// Presets per chain (selectable pairs)
const PRESETS: Record<number, { key: string; label: string; nft: string; debt: string }[]> = {
const PRESETS: Partial<Record<number, { key: string; label: string; nft: string; debt: string }[]>> = {
[base.id]: [
{ key: 'cbBTC-USDC', label: 'cbBTC-USDC', nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe', debt: '0xe93131620945a1273b48f57f453983d270b62dc7' },
{ key: 'WETH-USDC', label: 'WETH-USDC', nft: '0xab825f45e9e5d2459fb7a1527a8d0ca082c582f4', debt: '0x1be87d273d47c3832ab7853812e9a995a4de9eea' },
@@ -41,6 +50,11 @@ const PRESETS: Record<number, { key: string; label: string; nft: string; debt: s
[arbitrum.id]: [
{ key: 'USDTO-WBTC', label: 'USDTO-WBTC', nft: '0xedE6F5F8A9D6B90b1392Dcc9E7FD8A5B0192Bfe1', debt: '0x9Be2Cf73E62DD3b5dF4334D9A36888394822A33F' },
],
...(ENABLE_MAINNET ? {
[mainnet.id]: [
{ key: 'USDC-WETH', label: 'USDC-WETH (mainnet dummy)', nft: '0x0000000000000000000000000000000000000001', debt: '0x0000000000000000000000000000000000000002' },
],
} : {}),
};
export default function DappPage() {
@@ -158,7 +172,9 @@ export default function DappPage() {
if (age > 600) return; // ignore stale links >10min
const net = String(parsed.network || '').toUpperCase();
const presetIdx = Math.max(1, Number(parsed.preset || 1));
const nextChainId = net === 'BASE' ? base.id : ((net === 'ARBITRUM' || net === 'ARB') ? arbitrum.id : selectedChainId);
const nextChainId = net === 'BASE' ? base.id
: ((net === 'ARBITRUM' || net === 'ARB') ? arbitrum.id
: (ENABLE_MAINNET && net === 'MAINNET' ? mainnet.id : selectedChainId));
if (nextChainId !== selectedChainId) {
setSelectedChainId(nextChainId);
loadChainDefaults(nextChainId);
@@ -720,7 +736,7 @@ export default function DappPage() {
const debtRemaining = (row as any)?.debtAtThisSize as bigint | undefined;
const origin = (typeof window !== 'undefined' && window.location?.origin) ? window.location.origin : 'https://markets.mortgagefi.app';
const dappUrl = `${origin}/dapp`;
const networkSlug = selectedChainId === base.id ? 'BASE' : (selectedChainId === arbitrum.id ? 'ARBITRUM' : 'UNKNOWN');
const networkSlug = selectedChainId === base.id ? 'BASE' : (selectedChainId === arbitrum.id ? 'ARBITRUM' : (selectedChainId === mainnet.id ? 'MAINNET' : 'UNKNOWN'));
const presetIdx = Math.max(0, (PRESETS[selectedChainId]?.findIndex(p => p.key === presetKey) ?? 0)) + 1; // 1-based
const positionUrl = `${origin}/dapp/position/${networkSlug}/${presetIdx}/${row.tokenId.toString()}`;
const humanLeft = human(offset);

View File

@@ -12,9 +12,10 @@ const metadata = {
// Prefer custom RPCs to avoid public-provider rate limits (429)
const baseRpc = process.env.NEXT_PUBLIC_RPC_BASE;
const arbitrumRpc = process.env.NEXT_PUBLIC_RPC_ARBITRUM;
const enableMainnet = process.env.NEXT_PUBLIC_ENABLE_MAINNET === 'true';
export const config = createConfig({
chains: [base, arbitrum, mainnet, sepolia],
chains: [base, arbitrum, ...(enableMainnet ? [mainnet] : []), sepolia],
transports: {
[base.id]: baseRpc ? http(baseRpc, { batch: true, retryCount: 2, retryDelay: 250 }) : http(undefined, { batch: true, retryCount: 2, retryDelay: 250 }),
[arbitrum.id]: arbitrumRpc ? http(arbitrumRpc, { batch: true, retryCount: 2, retryDelay: 250 }) : http(undefined, { batch: true, retryCount: 2, retryDelay: 250 }),

View File

@@ -30,29 +30,23 @@ services:
- TZ=UTC
ports:
- "8080:8080"
volumes:
# Persist BadgerDB data so schedules survive restarts
- ../data/schedy:/data
restart: unless-stopped
frontend:
image: node:20-alpine
# image: node:20-alpine
image: git.manko.yoga/manawenuz/mortgagefi-frontend:alert
platform: linux/amd64
container_name: mortgagefi-frontend
working_dir: /app
# container_name: mortgagefi-frontend
env_file: .env.local
environment:
- HOST=0.0.0.0
- PORT=3000
- NEXT_PUBLIC_NTFY_URL=${NEXT_PUBLIC_NTFY_URL:-/ntfy}
- NEXT_PUBLIC_SCHEDY_URL=${NEXT_PUBLIC_SCHEDY_URL:-/schedy}
volumes:
- ./:/app
- /app/node_modules
command: >-
sh -c "apk add --no-cache python3 make g++ git libc6-compat
&& export PYTHON=/usr/bin/python3
&& npm ci --legacy-peer-deps --no-audit --no-fund
&& mkdir -p .next/static/development
&& npm run dev -- --hostname 0.0.0.0 --port 3000"
ports:
# ports:
- "3000:3000"
restart: unless-stopped
depends_on:

View File

@@ -5,6 +5,8 @@ const nextConfig: NextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
// Produce a self-contained server bundle at .next/standalone
output: 'standalone',
images: {
remotePatterns: [
{