added rough mainnet implementation and added backup contact for email
This commit is contained in:
14
.dockerignore
Normal file
14
.dockerignore
Normal 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
41
Dockerfile
Normal 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"]
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { useAccount, useChainId, useReadContract, useReadContracts, useSwitchChain, usePublicClient, useWriteContract, useSendTransaction } from 'wagmi';
|
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 { Abi, parseUnits } from 'viem';
|
||||||
import debtAbi from '@/ABIs/mortgagefiusdccbbtcupgraded.json';
|
import debtAbi from '@/ABIs/mortgagefiusdccbbtcupgraded.json';
|
||||||
import Link from 'next/link';
|
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' }] },
|
{ type: 'function', name: 'tokenOfOwnerByIndex', stateMutability: 'view', inputs: [{ name: 'owner', type: 'address' }, { name: 'index', type: 'uint256' }], outputs: [{ type: 'uint256' }] },
|
||||||
] as const satisfies Abi;
|
] as const satisfies Abi;
|
||||||
|
|
||||||
|
const ENABLE_MAINNET = process.env.NEXT_PUBLIC_ENABLE_MAINNET === 'true';
|
||||||
|
|
||||||
const DEFAULTS = {
|
const DEFAULTS = {
|
||||||
[base.id]: {
|
[base.id]: {
|
||||||
nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe',
|
nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe',
|
||||||
@@ -30,10 +32,17 @@ const DEFAULTS = {
|
|||||||
nft: '0xedE6F5F8A9D6B90b1392Dcc9E7FD8A5B0192Bfe1',
|
nft: '0xedE6F5F8A9D6B90b1392Dcc9E7FD8A5B0192Bfe1',
|
||||||
debt: '0x9Be2Cf73E62DD3b5dF4334D9A36888394822A33F',
|
debt: '0x9Be2Cf73E62DD3b5dF4334D9A36888394822A33F',
|
||||||
},
|
},
|
||||||
|
...(ENABLE_MAINNET ? {
|
||||||
|
[mainnet.id]: {
|
||||||
|
// Dummy placeholders for future USDC-WETH mainnet vault
|
||||||
|
nft: '0x0000000000000000000000000000000000000001',
|
||||||
|
debt: '0x0000000000000000000000000000000000000002',
|
||||||
|
},
|
||||||
|
} : {}),
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Presets per chain (selectable pairs)
|
// 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]: [
|
[base.id]: [
|
||||||
{ key: 'cbBTC-USDC', label: 'cbBTC-USDC', nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe', debt: '0xe93131620945a1273b48f57f453983d270b62dc7' },
|
{ key: 'cbBTC-USDC', label: 'cbBTC-USDC', nft: '0xcc9a350c5b1e1c9ecd23d376e6618cdfd6bbbdbe', debt: '0xe93131620945a1273b48f57f453983d270b62dc7' },
|
||||||
{ key: 'WETH-USDC', label: 'WETH-USDC', nft: '0xab825f45e9e5d2459fb7a1527a8d0ca082c582f4', debt: '0x1be87d273d47c3832ab7853812e9a995a4de9eea' },
|
{ 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]: [
|
[arbitrum.id]: [
|
||||||
{ key: 'USDTO-WBTC', label: 'USDTO-WBTC', nft: '0xedE6F5F8A9D6B90b1392Dcc9E7FD8A5B0192Bfe1', debt: '0x9Be2Cf73E62DD3b5dF4334D9A36888394822A33F' },
|
{ 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() {
|
export default function DappPage() {
|
||||||
@@ -158,7 +172,9 @@ export default function DappPage() {
|
|||||||
if (age > 600) return; // ignore stale links >10min
|
if (age > 600) return; // ignore stale links >10min
|
||||||
const net = String(parsed.network || '').toUpperCase();
|
const net = String(parsed.network || '').toUpperCase();
|
||||||
const presetIdx = Math.max(1, Number(parsed.preset || 1));
|
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) {
|
if (nextChainId !== selectedChainId) {
|
||||||
setSelectedChainId(nextChainId);
|
setSelectedChainId(nextChainId);
|
||||||
loadChainDefaults(nextChainId);
|
loadChainDefaults(nextChainId);
|
||||||
@@ -720,7 +736,7 @@ export default function DappPage() {
|
|||||||
const debtRemaining = (row as any)?.debtAtThisSize as bigint | undefined;
|
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 origin = (typeof window !== 'undefined' && window.location?.origin) ? window.location.origin : 'https://markets.mortgagefi.app';
|
||||||
const dappUrl = `${origin}/dapp`;
|
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 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 positionUrl = `${origin}/dapp/position/${networkSlug}/${presetIdx}/${row.tokenId.toString()}`;
|
||||||
const humanLeft = human(offset);
|
const humanLeft = human(offset);
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ const metadata = {
|
|||||||
// Prefer custom RPCs to avoid public-provider rate limits (429)
|
// Prefer custom RPCs to avoid public-provider rate limits (429)
|
||||||
const baseRpc = process.env.NEXT_PUBLIC_RPC_BASE;
|
const baseRpc = process.env.NEXT_PUBLIC_RPC_BASE;
|
||||||
const arbitrumRpc = process.env.NEXT_PUBLIC_RPC_ARBITRUM;
|
const arbitrumRpc = process.env.NEXT_PUBLIC_RPC_ARBITRUM;
|
||||||
|
const enableMainnet = process.env.NEXT_PUBLIC_ENABLE_MAINNET === 'true';
|
||||||
|
|
||||||
export const config = createConfig({
|
export const config = createConfig({
|
||||||
chains: [base, arbitrum, mainnet, sepolia],
|
chains: [base, arbitrum, ...(enableMainnet ? [mainnet] : []), sepolia],
|
||||||
transports: {
|
transports: {
|
||||||
[base.id]: baseRpc ? http(baseRpc, { batch: true, retryCount: 2, retryDelay: 250 }) : http(undefined, { batch: true, retryCount: 2, retryDelay: 250 }),
|
[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 }),
|
[arbitrum.id]: arbitrumRpc ? http(arbitrumRpc, { batch: true, retryCount: 2, retryDelay: 250 }) : http(undefined, { batch: true, retryCount: 2, retryDelay: 250 }),
|
||||||
|
|||||||
@@ -30,29 +30,23 @@ services:
|
|||||||
- TZ=UTC
|
- TZ=UTC
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
# Persist BadgerDB data so schedules survive restarts
|
||||||
|
- ../data/schedy:/data
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: node:20-alpine
|
# image: node:20-alpine
|
||||||
|
image: git.manko.yoga/manawenuz/mortgagefi-frontend:alert
|
||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
container_name: mortgagefi-frontend
|
# container_name: mortgagefi-frontend
|
||||||
working_dir: /app
|
|
||||||
env_file: .env.local
|
env_file: .env.local
|
||||||
environment:
|
environment:
|
||||||
- HOST=0.0.0.0
|
- HOST=0.0.0.0
|
||||||
- PORT=3000
|
- PORT=3000
|
||||||
- NEXT_PUBLIC_NTFY_URL=${NEXT_PUBLIC_NTFY_URL:-/ntfy}
|
- NEXT_PUBLIC_NTFY_URL=${NEXT_PUBLIC_NTFY_URL:-/ntfy}
|
||||||
- NEXT_PUBLIC_SCHEDY_URL=${NEXT_PUBLIC_SCHEDY_URL:-/schedy}
|
- NEXT_PUBLIC_SCHEDY_URL=${NEXT_PUBLIC_SCHEDY_URL:-/schedy}
|
||||||
volumes:
|
# ports:
|
||||||
- ./:/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:
|
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ const nextConfig: NextConfig = {
|
|||||||
eslint: {
|
eslint: {
|
||||||
ignoreDuringBuilds: true,
|
ignoreDuringBuilds: true,
|
||||||
},
|
},
|
||||||
|
// Produce a self-contained server bundle at .next/standalone
|
||||||
|
output: 'standalone',
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user