fix alot of things
This commit is contained in:
29
.env.backend
29
.env.backend
@@ -1,29 +0,0 @@
|
|||||||
MONGO_URI=mongodb://root:OkZl9TEPteFk75@captain.inboxi.ng/mydatabase?authSource=admin
|
|
||||||
PORT=3001
|
|
||||||
|
|
||||||
JWT_SECRET=450417bc552e573f95c6d115b45dee27b8c544e5015ec8dd34147d59e1b0c360e3ab705e08511285bd0f5900e11cc4b6841f6391b24dc2c0e86ac2de473f4cb60b18fdc995304a27225db7ea13cece60f4afa50296a7b640b2042fe9072e1cd675cbd134ffeef9ee5a4b234830c53b98b21dcf8224acc6aec3745f5b7e46106eb2db946263cbf3d41add1a269d96de4034533cc9dcf1b74a155eccd0eae55cd958150c31ef0518346ac0471b7b5c83a6e4b26f9526b1c6702c65c38166db4bde57da1ba65a425e4ffba14b86d0279b907bd2eb29a86fd5b57ed78f5319dd5d78dc258cd801595978e042c4a2ca355825d894f8c4fcd39b57a3f78b1a9fd563758f0688d8f3b439c1cdfd161eb92e5ffea647b3a69c2889acd79e33c3a7dd64d32ddd14919be47cbfc46cea68df355f041530a3b0cddfb1042f7f96af7316a66a09fde4e18391dbe5d001a75ae8f8d44edc764b418a7525f55d5d593ca219336f467090b3d329528fd6535ad2c706eda9ed481da824931167dc4fa44a51cdbd13202ffea1375380c8dbdfec85665612c66d2df4bb44a322c54915fb46da50db6ff8e02d4b602069f0267fd29ec4bf865ac03597488d4ac59837fc1d51704f8dcf176681713ee9a24c3abaf58907f01581f7b2ac44a98cf177d6403ef1cf2b61e92cfa2939654ac9ef805d717c846520a02e6e054bcd2fee5394e1a05eb3d85f0d
|
|
||||||
INTERNAL_API_KEY=5cffe0dedbbcc8761f6ddc7dc7cc2d299d599
|
|
||||||
|
|
||||||
ENCRYPTION_KEY=48c66ee5a54e596e2029ea832a512401099533ece34cb0fbbb8c4023ca68ba8e
|
|
||||||
ENCRYPTION_IV=539e26d426cd4bac9844a8e446d63ab1
|
|
||||||
|
|
||||||
BTC_RPC_USER=your_rpc_user
|
|
||||||
BTC_RPC_PASSWORD=your_rpc_password
|
|
||||||
|
|
||||||
BTC_RPC_HOST=127.0.0.1
|
|
||||||
BTC_RPC_PORT=8332
|
|
||||||
|
|
||||||
LTC_RPC_USER=notiiwasntherexdddd
|
|
||||||
LTC_RPC_PASSWORD=NYwsxePgMrThiapHnfCzUfaEfVlNKZECwvlqhHcWjerlZfcaTp
|
|
||||||
|
|
||||||
LTC_RPC_HOST=127.0.0.1
|
|
||||||
LTC_RPC_PORT=9332
|
|
||||||
|
|
||||||
XMR_RPC_USER=your_rpc_user
|
|
||||||
XMR_RPC_PASSWORD=your_rpc_password
|
|
||||||
|
|
||||||
XMR_RPC_HOST=127.0.0.1
|
|
||||||
XMR_RPC_PORT=18081
|
|
||||||
|
|
||||||
OkZl9TEPteFk75=OkZl9TEPteFk75
|
|
||||||
WL4E8H72nvSF=WL4E8H72nvSF
|
|
||||||
13
.env.tor
13
.env.tor
@@ -1,13 +0,0 @@
|
|||||||
# Tor-specific environment variables
|
|
||||||
# Using relative URLs for maximum compatibility
|
|
||||||
NEXT_PUBLIC_API_URL=/api
|
|
||||||
# Flag to indicate we're running in Tor mode
|
|
||||||
NEXT_PUBLIC_TOR_MODE=true
|
|
||||||
# Use relative URLs for all API communications - critical for Tor
|
|
||||||
SERVER_API_URL=/api
|
|
||||||
# Disable HTTPS for Tor communication (onion services already provide encryption)
|
|
||||||
USE_HTTPS=false
|
|
||||||
# Tor uses the same port for both internal and external communications
|
|
||||||
INTERNAL_API_PORT=3000
|
|
||||||
# Tell the app to check for onion addresses
|
|
||||||
CHECK_ONION_ADDRESS=true
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# Ember Market Integrated Application
|
|
||||||
|
|
||||||
This project combines both the Ember Market frontend (Next.js) and backend (Express) into a single application. This approach eliminates the need to run two separate servers and avoids routing conflicts between Next.js and Express.
|
|
||||||
|
|
||||||
## Setup Instructions
|
|
||||||
|
|
||||||
1. **Clone both repositories** if you haven't already:
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/your-username/ember-market-frontend.git
|
|
||||||
git clone https://github.com/your-username/ember-market-backend.git
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Install dependencies**:
|
|
||||||
```bash
|
|
||||||
cd ember-market-frontend
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Run the setup script** to copy backend files to the frontend project:
|
|
||||||
```bash
|
|
||||||
npm run setup-backend
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Update environment variables**:
|
|
||||||
- The setup script copies the backend `.env` file to `.env.backend` in the frontend project
|
|
||||||
- Make sure to review and adjust environment variables as needed
|
|
||||||
- Ensure MongoDB connection string and other critical variables are set correctly
|
|
||||||
|
|
||||||
## Running the Application
|
|
||||||
|
|
||||||
### Development Mode
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev:custom
|
|
||||||
```
|
|
||||||
|
|
||||||
This starts the combined server in development mode on port 3000 (or the port specified in your environment variables).
|
|
||||||
|
|
||||||
### Production Mode
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run build
|
|
||||||
npm run start:custom
|
|
||||||
```
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
This integration uses a custom Express server that:
|
|
||||||
|
|
||||||
1. Handles API routes at `/api/*` using the existing Express backend code
|
|
||||||
2. Delegates all other routes to Next.js to handle frontend rendering
|
|
||||||
|
|
||||||
### Key Files
|
|
||||||
|
|
||||||
- `server.js`: Custom server that combines Express and Next.js
|
|
||||||
- `setup-backend.js`: Script to copy backend files into the frontend project
|
|
||||||
- `next.config.mjs`: Configured to work with the custom Express server
|
|
||||||
|
|
||||||
## API Routes
|
|
||||||
|
|
||||||
All backend API routes are available at the same paths as before, but now they're served from the same server as your frontend:
|
|
||||||
|
|
||||||
- Authentication: `/api/auth/*`
|
|
||||||
- Products: `/api/products/*`
|
|
||||||
- Orders: `/api/orders/*`
|
|
||||||
- etc.
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
When making changes:
|
|
||||||
|
|
||||||
1. **Frontend changes**: Modify files in the frontend project as usual
|
|
||||||
2. **Backend changes**: You have two options:
|
|
||||||
- Make changes in the original backend repo and run `npm run setup-backend` to sync
|
|
||||||
- Make changes directly in the frontend project's `backend/` directory
|
|
||||||
|
|
||||||
Remember that changes made directly in the frontend project's `backend/` directory won't automatically sync back to the original backend repository.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
- **Port conflicts**: Make sure no other service is using port 3000 (or your configured port)
|
|
||||||
- **MongoDB connection issues**: Verify your connection string in the environment variables
|
|
||||||
- **Path issues**: Ensure paths in imports are correct for the new project structure
|
|
||||||
28
Dockerfile
28
Dockerfile
@@ -7,9 +7,7 @@ RUN npm install --force
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Set build-time environment variables to use relative URLs
|
ENV NEXT_PUBLIC_API_URL=https://internal-api.inboxi.ng/api
|
||||||
ENV NEXT_PUBLIC_API_URL=/api
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
|
|
||||||
# Build the Next.js application
|
# Build the Next.js application
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@@ -26,30 +24,12 @@ RUN mkdir -p /app/public
|
|||||||
COPY --from=builder /app/package.json /app/package-lock.json ./
|
COPY --from=builder /app/package.json /app/package-lock.json ./
|
||||||
COPY --from=builder /app/.next ./.next
|
COPY --from=builder /app/.next ./.next
|
||||||
COPY --from=builder /app/node_modules ./node_modules
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
COPY --from=builder /app/server.js ./
|
|
||||||
COPY --from=builder /app/.env.tor ./
|
|
||||||
COPY --from=builder /app/.env.backend ./
|
|
||||||
COPY --from=builder /app/public ./public
|
|
||||||
|
|
||||||
# If you have a backend folder, copy it as well
|
|
||||||
COPY --from=builder /app/backend ./backend
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Set runtime environment variables - these will be overridden by .env.tor when running in Tor mode
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
# Use relative URLs for maximum Tor compatibility
|
ENV NEXT_PUBLIC_API_URL=https://internal-api.inboxi.ng/api
|
||||||
ENV NEXT_PUBLIC_API_URL=/api
|
|
||||||
# Running in Tor mode
|
|
||||||
ENV NEXT_PUBLIC_TOR_MODE=true
|
|
||||||
# Use relative URLs for server components - critical for Tor
|
|
||||||
ENV SERVER_API_URL=/api
|
|
||||||
# Disable HTTPS for onion services (they're already encrypted)
|
|
||||||
ENV USE_HTTPS=false
|
|
||||||
# Set port for internal API calls
|
|
||||||
ENV INTERNAL_API_PORT=3000
|
|
||||||
# Disable telemetry
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
|
|
||||||
# Start Next.js server
|
# Start Next.js server
|
||||||
CMD ["npm", "run", "start:tor"]
|
CMD ["npm", "run", "start"]
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
# Ember Market on Tor
|
|
||||||
|
|
||||||
This document explains how to run Ember Market in a Tor-friendly way, ensuring compatibility with .onion domains and the Tor network.
|
|
||||||
|
|
||||||
## Tor-Optimized Configuration
|
|
||||||
|
|
||||||
The application is designed to work seamlessly with Tor by:
|
|
||||||
|
|
||||||
1. Using relative URLs throughout the codebase
|
|
||||||
2. Avoiding hardcoded domain names
|
|
||||||
3. Ensuring all API requests work regardless of the domain
|
|
||||||
|
|
||||||
## Running in Tor Mode
|
|
||||||
|
|
||||||
To start the application in Tor mode:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Development
|
|
||||||
npm run dev:tor
|
|
||||||
|
|
||||||
# Production
|
|
||||||
npm run start:tor
|
|
||||||
```
|
|
||||||
|
|
||||||
These commands use the `.env.tor` configuration file, which sets appropriate environment variables for Tor usage.
|
|
||||||
|
|
||||||
## Accessing via .onion Domain
|
|
||||||
|
|
||||||
When deployed to a Tor hidden service:
|
|
||||||
|
|
||||||
1. The application automatically detects the .onion domain
|
|
||||||
2. All API requests are made relative to the current domain
|
|
||||||
3. No changes are needed to the codebase or configuration
|
|
||||||
|
|
||||||
## Security Considerations for Tor
|
|
||||||
|
|
||||||
- All API requests use relative URLs to prevent domain leakage
|
|
||||||
- Authentication is performed on the same domain to maintain anonymity
|
|
||||||
- No external resources are loaded that could compromise Tor anonymity
|
|
||||||
|
|
||||||
## Deployment to a Tor Hidden Service
|
|
||||||
|
|
||||||
To deploy as a Tor hidden service:
|
|
||||||
|
|
||||||
1. Set up a Tor hidden service pointing to the application port (default: 3000)
|
|
||||||
2. Use the `start:tor` script to ensure proper environment variables
|
|
||||||
3. The application will automatically work with the .onion domain
|
|
||||||
|
|
||||||
## Checking Tor Compatibility
|
|
||||||
|
|
||||||
To verify the application is working correctly with Tor:
|
|
||||||
|
|
||||||
1. Check network requests in the browser's developer tools
|
|
||||||
2. All API requests should go to relative paths (e.g., `/api/auth/me`)
|
|
||||||
3. No absolute URLs should be used in requests
|
|
||||||
|
|
||||||
## Troubleshooting Tor Issues
|
|
||||||
|
|
||||||
- If authentication fails, check that cookies are enabled in your Tor browser
|
|
||||||
- If API requests fail, verify that the application is accessible via the .onion domain
|
|
||||||
- For security issues, ensure JavaScript is enabled for the .onion domain in Tor browser settings
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
import Content from "@/components/dashboard/content";
|
import Content from "@/components/dashboard/content";
|
||||||
import { fetchClient } from '@/lib/client-service';
|
import { fetchServer } from '@/lib/server-service';
|
||||||
|
|
||||||
// ✅ Corrected Vendor Type
|
// ✅ Corrected Vendor Type
|
||||||
interface Vendor {
|
interface Vendor {
|
||||||
@@ -25,43 +22,13 @@ interface OrderStats {
|
|||||||
cancelledOrders: number;
|
cancelledOrders: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default async function DashboardPage() {
|
||||||
const [vendor, setVendor] = useState<Vendor | null>(null);
|
const [userResponse, orderStats] = await Promise.all([
|
||||||
const [orderStats, setOrderStats] = useState<OrderStats | null>(null);
|
fetchServer<User>("/auth/me"),
|
||||||
const [loading, setLoading] = useState(true);
|
fetchServer<OrderStats>("/orders/stats"),
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function fetchData() {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
// Fetch data from API using relative URLs and client-side fetch
|
|
||||||
const [userResponse, stats] = await Promise.all([
|
|
||||||
fetchClient<User>("auth/me"),
|
|
||||||
fetchClient<OrderStats>("orders/stats"),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setVendor(userResponse.vendor);
|
const vendor = userResponse.vendor;
|
||||||
setOrderStats(stats);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error fetching dashboard data:', err);
|
|
||||||
setError('Failed to load dashboard data');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <Dashboard><div>Loading dashboard...</div></Dashboard>;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error || !vendor || !orderStats) {
|
|
||||||
return <Dashboard><div>Error: {error || 'Failed to load data'}</div></Dashboard>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dashboard>
|
<Dashboard>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ services:
|
|||||||
- web
|
- web
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- NEXT_PUBLIC_API_URL=/api
|
- NEXT_PUBLIC_API_URL=https://internal-api.inboxi.ng/api
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
// Helper function to verify authentication with the local API
|
|
||||||
export async function verifyAuth(token: string) {
|
|
||||||
try {
|
|
||||||
let authEndpoint;
|
|
||||||
const torMode = process.env.NEXT_PUBLIC_TOR_MODE === 'true';
|
|
||||||
|
|
||||||
// Check if we're running in a browser environment
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
// For Tor mode in browser, prefer relative URLs
|
|
||||||
if (torMode) {
|
|
||||||
authEndpoint = '/api/auth/me';
|
|
||||||
console.log(`Tor mode: Using relative URL for auth endpoint: ${authEndpoint}`);
|
|
||||||
} else {
|
|
||||||
// Use the current origin in regular browser environments
|
|
||||||
const origin = window.location.origin;
|
|
||||||
authEndpoint = new URL('/api/auth/me', origin).toString();
|
|
||||||
console.log(`Using browser origin for auth endpoint: ${authEndpoint}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// For SSR or when window is not available (e.g. in Docker container)
|
|
||||||
|
|
||||||
// For Tor mode, always use relative URLs
|
|
||||||
if (torMode) {
|
|
||||||
authEndpoint = '/api/auth/me';
|
|
||||||
console.log(`Tor mode SSR: Using relative URL for auth endpoint: ${authEndpoint}`);
|
|
||||||
}
|
|
||||||
// Use the environment variable if available
|
|
||||||
else if (process.env.SERVER_API_URL) {
|
|
||||||
// If SERVER_API_URL already includes /auth/me, don't append it again
|
|
||||||
if (process.env.SERVER_API_URL.includes('/auth/me')) {
|
|
||||||
authEndpoint = process.env.SERVER_API_URL;
|
|
||||||
} else {
|
|
||||||
// Otherwise append the endpoint to the base URL
|
|
||||||
authEndpoint = `${process.env.SERVER_API_URL}/auth/me`;
|
|
||||||
}
|
|
||||||
console.log(`Using SERVER_API_URL for auth endpoint: ${authEndpoint}`);
|
|
||||||
} else {
|
|
||||||
// Fallback for local development
|
|
||||||
const protocol = (process.env.USE_HTTPS === 'false') ? 'http' : 'https';
|
|
||||||
const port = process.env.INTERNAL_API_PORT || '3000';
|
|
||||||
authEndpoint = `${protocol}://localhost:${port}/api/auth/me`;
|
|
||||||
console.log(`Using fallback for auth endpoint: ${authEndpoint}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Verifying authentication with endpoint: ${authEndpoint}`);
|
|
||||||
|
|
||||||
const response = await fetch(authEndpoint, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
// Prevent caching of auth requests
|
|
||||||
cache: 'no-store'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
console.error(`Auth verification failed: ${response.status}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Authentication verification failed:", error);
|
|
||||||
console.error("Error details:", error instanceof Error ? error.message : 'Unknown error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,44 +21,31 @@ function getAuthToken(): string | null {
|
|||||||
?.split('=')[1] || null;
|
?.split('=')[1] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the API base URL for client-side fetch calls
|
|
||||||
*/
|
|
||||||
function getClientApiBaseUrl(): string {
|
|
||||||
// For client-side, we can access window.location if in browser
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
// Use the same origin (which includes the correct port)
|
|
||||||
return `${window.location.origin}/api`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback when window is not available
|
|
||||||
// For development mode, use port 3001 to match our server
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
return 'http://localhost:3001/api';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default fallback - relative URL
|
|
||||||
return '/api';
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchClient<T>(
|
export async function fetchClient<T>(
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
options: FetchOptions = {}
|
options: FetchOptions = {}
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const { method = 'GET', body, headers = {}, ...rest } = options;
|
const { method = 'GET', body, headers = {}, ...rest } = options;
|
||||||
|
|
||||||
try {
|
// Get the base API URL from environment or fallback
|
||||||
// Get the base API URL
|
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
||||||
const baseUrl = getClientApiBaseUrl();
|
|
||||||
|
|
||||||
// Ensure endpoint doesn't start with a slash if baseUrl ends with one
|
// Ensure the endpoint starts with a slash
|
||||||
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||||
|
|
||||||
// Ensure baseUrl ends with a slash if it doesn't already
|
// For the specific case of internal-api.inboxi.ng - remove duplicate /api
|
||||||
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
let url;
|
||||||
|
if (apiUrl.includes('internal-api.inboxi.ng')) {
|
||||||
// Combine them for the final URL
|
// Special case for internal-api.inboxi.ng
|
||||||
const url = `${normalizedBaseUrl}${normalizedEndpoint}`;
|
if (normalizedEndpoint.startsWith('/api/')) {
|
||||||
|
url = `${apiUrl}${normalizedEndpoint.substring(4)}`; // Remove the /api part
|
||||||
|
} else {
|
||||||
|
url = `${apiUrl}${normalizedEndpoint}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal case for other environments
|
||||||
|
url = `${apiUrl}${normalizedEndpoint}`;
|
||||||
|
}
|
||||||
|
|
||||||
// Get auth token from cookies
|
// Get auth token from cookies
|
||||||
const authToken = getAuthToken();
|
const authToken = getAuthToken();
|
||||||
@@ -92,6 +79,7 @@ export async function fetchClient<T>(
|
|||||||
fetchOptions.body = JSON.stringify(body);
|
fetchOptions.body = JSON.stringify(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const response = await fetch(url, fetchOptions);
|
const response = await fetch(url, fetchOptions);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -109,7 +97,6 @@ export async function fetchClient<T>(
|
|||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('API request failed:', error);
|
console.error('API request failed:', error);
|
||||||
console.error('Error details:', error instanceof Error ? error.message : 'Unknown error');
|
|
||||||
|
|
||||||
// Only show toast if this is a client-side error (not during SSR)
|
// Only show toast if this is a client-side error (not during SSR)
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
|
|||||||
@@ -1,77 +1,6 @@
|
|||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
import { redirect } from 'next/navigation';
|
import { redirect } from 'next/navigation';
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the base URL for server API requests with proper fallbacks
|
|
||||||
*/
|
|
||||||
function getBaseUrl() {
|
|
||||||
// Check if we're running in Tor mode
|
|
||||||
const torMode = process.env.NEXT_PUBLIC_TOR_MODE === 'true';
|
|
||||||
|
|
||||||
// First check for the specific server API URL environment variable
|
|
||||||
if (process.env.SERVER_API_URL) {
|
|
||||||
console.log(`Using SERVER_API_URL: ${process.env.SERVER_API_URL}`);
|
|
||||||
|
|
||||||
// If we're in Tor mode and the SERVER_API_URL is set to a relative path, use it directly
|
|
||||||
if (torMode && process.env.SERVER_API_URL.startsWith('/')) {
|
|
||||||
return process.env.SERVER_API_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return process.env.SERVER_API_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For server components, we normally would use environment variables
|
|
||||||
// But we need to be careful with how they're accessed
|
|
||||||
|
|
||||||
// Try to get the API URL from environment variables
|
|
||||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
|
|
||||||
|
|
||||||
// Check if we're running in a container/production environment
|
|
||||||
const inContainer = process.env.NODE_ENV === 'production';
|
|
||||||
|
|
||||||
// If in Tor mode, prefer relative URLs
|
|
||||||
if (torMode && apiUrl && apiUrl.startsWith('/')) {
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to get the host from somewhere to construct the URL
|
|
||||||
// In production, we can rely on the VERCEL_URL or similar
|
|
||||||
if (process.env.VERCEL_URL) {
|
|
||||||
return `https://${process.env.VERCEL_URL}/api`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a configured API URL, use that
|
|
||||||
if (apiUrl) {
|
|
||||||
// If it's already an absolute URL, use it
|
|
||||||
if (apiUrl.startsWith('http')) {
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For container environments, use the internal port
|
|
||||||
const port = process.env.INTERNAL_API_PORT || '3000';
|
|
||||||
const protocol = (process.env.USE_HTTPS === 'false') ? 'http' : 'https';
|
|
||||||
|
|
||||||
// If in Tor mode, prefer relative URLs
|
|
||||||
if (torMode) {
|
|
||||||
return apiUrl.startsWith('/') ? apiUrl : `/${apiUrl}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, it's likely a relative path like /api
|
|
||||||
// Use localhost with the correct port for container environments
|
|
||||||
return `${protocol}://localhost:${port}${apiUrl.startsWith('/') ? apiUrl : `/${apiUrl}`}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last resort fallback - if in Tor mode, use a relative URL
|
|
||||||
if (torMode) {
|
|
||||||
return '/api';
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular container environments
|
|
||||||
const protocol = (process.env.USE_HTTPS === 'false') ? 'http' : 'https';
|
|
||||||
const port = process.env.INTERNAL_API_PORT || '3000';
|
|
||||||
return `${protocol}://localhost:${port}/api`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server-side fetch wrapper with authentication.
|
* Server-side fetch wrapper with authentication.
|
||||||
*/
|
*/
|
||||||
@@ -85,52 +14,8 @@ export async function fetchServer<T = unknown>(
|
|||||||
if (!authToken) redirect('/login');
|
if (!authToken) redirect('/login');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const baseUrl = getBaseUrl();
|
console.log(`${endpoint}`)
|
||||||
const torMode = process.env.NEXT_PUBLIC_TOR_MODE === 'true';
|
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${endpoint}`, {
|
||||||
|
|
||||||
// Special handling for Tor mode
|
|
||||||
if (torMode) {
|
|
||||||
// For Tor, we need to be extra careful with URL construction
|
|
||||||
|
|
||||||
// Remove leading slash from endpoint if present
|
|
||||||
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
|
||||||
|
|
||||||
// If baseUrl is a relative path (starts with /)
|
|
||||||
if (baseUrl.startsWith('/')) {
|
|
||||||
// Combine paths carefully to create a relative URL
|
|
||||||
const url = `${baseUrl}${baseUrl.endsWith('/') ? '' : '/'}${normalizedEndpoint}`;
|
|
||||||
console.log(`Tor mode: Using relative URL for server fetch: ${url}`);
|
|
||||||
|
|
||||||
const res = await fetch(url, {
|
|
||||||
...options,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${authToken}`,
|
|
||||||
...options.headers,
|
|
||||||
},
|
|
||||||
cache: 'no-store',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 401) redirect('/login');
|
|
||||||
if (!res.ok) throw new Error(`Request failed: ${res.statusText}`);
|
|
||||||
|
|
||||||
return res.json();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular URL construction for non-Tor environments
|
|
||||||
// Ensure endpoint doesn't start with a slash if baseUrl ends with one
|
|
||||||
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
|
||||||
|
|
||||||
// Ensure baseUrl ends with a slash if it doesn't already
|
|
||||||
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
||||||
|
|
||||||
// Combine them to get a complete URL
|
|
||||||
const url = `${normalizedBaseUrl}${normalizedEndpoint}`;
|
|
||||||
|
|
||||||
console.log(`Server fetch to: ${url}`);
|
|
||||||
|
|
||||||
const res = await fetch(url, {
|
|
||||||
...options,
|
...options,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Helper function to construct proper URLs for server components.
|
|
||||||
* In Next.js server components, relative URLs don't work in fetch() calls.
|
|
||||||
*/
|
|
||||||
export function getServerApiUrl(endpoint: string): string {
|
|
||||||
// Base API URL - use a hardcoded value for server components
|
|
||||||
// This must be an absolute URL with protocol and domain
|
|
||||||
const baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api';
|
|
||||||
|
|
||||||
// Ensure endpoint doesn't start with a slash if baseUrl ends with one
|
|
||||||
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
|
|
||||||
|
|
||||||
// Ensure the baseUrl ends with a slash if it doesn't already
|
|
||||||
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
||||||
|
|
||||||
// Combine them to get a complete URL
|
|
||||||
return `${normalizedBaseUrl}${normalizedEndpoint}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to detect if code is running on server or client
|
|
||||||
*/
|
|
||||||
export function isServer(): boolean {
|
|
||||||
return typeof window === 'undefined';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to detect if code is running in development mode
|
|
||||||
*/
|
|
||||||
export function isDevelopment(): boolean {
|
|
||||||
return process.env.NODE_ENV === 'development';
|
|
||||||
}
|
|
||||||
@@ -10,30 +10,19 @@ export async function middleware(req: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Make sure we use a complete URL with protocol
|
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/me`, {
|
||||||
// When running locally with integrated backend, we need to specify the full URL including protocol
|
|
||||||
const origin = req.nextUrl.origin;
|
|
||||||
const authEndpoint = new URL("/api/auth/me", origin).toString();
|
|
||||||
|
|
||||||
console.log("Verifying authentication with endpoint:", authEndpoint);
|
|
||||||
|
|
||||||
const res = await fetch(authEndpoint, {
|
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
// Ensure we're not caching authentication checks
|
|
||||||
cache: 'no-store'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
console.error(`Auth check failed with status: ${res.status}`);
|
|
||||||
return NextResponse.redirect(new URL("/auth/login", req.url));
|
return NextResponse.redirect(new URL("/auth/login", req.url));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Authentication validation failed:", error);
|
console.error("Authentication validation failed:", error);
|
||||||
console.error("Error details:", error instanceof Error ? error.message : 'Unknown error');
|
|
||||||
return NextResponse.redirect(new URL("/auth/login", req.url));
|
return NextResponse.redirect(new URL("/auth/login", req.url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,46 +8,6 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Disable Next.js handling of API routes that our Express server will handle
|
|
||||||
async rewrites() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
// Don't rewrite actual Next.js API routes
|
|
||||||
source: "/api/_next/:path*",
|
|
||||||
destination: "/api/_next/:path*",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Rewrite API requests to be handled by our custom Express server
|
|
||||||
source: "/api/:path*",
|
|
||||||
destination: "/api/:path*",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
// Make environment variables available to both client and server components
|
|
||||||
env: {
|
|
||||||
// For integrated backend, use http://localhost:3000/api
|
|
||||||
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api',
|
|
||||||
},
|
|
||||||
// Prevent dynamic URLs from being hard-coded at build time
|
|
||||||
// This is important for Tor compatibility
|
|
||||||
experimental: {
|
|
||||||
// This prevents URLs from being hardcoded at build time
|
|
||||||
esmExternals: true,
|
|
||||||
},
|
|
||||||
// Ensure server components can handle URL objects
|
|
||||||
serverComponentsExternalPackages: ['next/dist/compiled/path-to-regexp'],
|
|
||||||
// Allow server-side fetch calls to the local API
|
|
||||||
serverRuntimeConfig: {
|
|
||||||
apiUrl: 'http://localhost:3000/api',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Special handling for server components
|
|
||||||
webpack: (config, { isServer }) => {
|
|
||||||
if (isServer) {
|
|
||||||
// Server-side specific config
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
2183
package-lock.json
generated
2183
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@@ -2,16 +2,10 @@
|
|||||||
"name": "my-v0-project",
|
"name": "my-v0-project",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"dev:custom": "node server.js",
|
|
||||||
"dev:tor": "NODE_ENV=production node -r dotenv/config server.js dotenv_config_path=.env.tor",
|
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"start:custom": "NODE_ENV=production node server.js",
|
|
||||||
"start:tor": "NODE_ENV=production node -r dotenv/config server.js dotenv_config_path=.env.tor",
|
|
||||||
"setup-backend": "node setup-backend.js",
|
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -45,28 +39,17 @@
|
|||||||
"@radix-ui/react-tooltip": "^1.1.6",
|
"@radix-ui/react-tooltip": "^1.1.6",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"axios": "^1.8.1",
|
"axios": "^1.8.1",
|
||||||
"bcrypt": "^5.1.1",
|
|
||||||
"bcryptjs": "^2.4.3",
|
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "1.0.4",
|
"cmdk": "1.0.4",
|
||||||
"cors": "^2.8.5",
|
|
||||||
"date-fns": "4.1.0",
|
"date-fns": "4.1.0",
|
||||||
"dotenv": "^16.4.7",
|
|
||||||
"embla-carousel-react": "8.5.1",
|
"embla-carousel-react": "8.5.1",
|
||||||
"express": "^4.21.2",
|
|
||||||
"form-data": "^4.0.2",
|
"form-data": "^4.0.2",
|
||||||
"input-otp": "1.4.1",
|
"input-otp": "1.4.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"ky": "^1.7.5",
|
|
||||||
"lucide-react": "^0.454.0",
|
"lucide-react": "^0.454.0",
|
||||||
"mongoose": "^8.9.6",
|
|
||||||
"mongoose-sequence": "^6.0.1",
|
|
||||||
"multer": "^1.4.5-lts.1",
|
|
||||||
"next": "14.2.16",
|
"next": "14.2.16",
|
||||||
"next-themes": "latest",
|
"next-themes": "latest",
|
||||||
"openpgp": "^6.1.0",
|
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-day-picker": "8.10.1",
|
"react-day-picker": "8.10.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
@@ -74,11 +57,9 @@
|
|||||||
"react-markdown": "^10.0.0",
|
"react-markdown": "^10.0.0",
|
||||||
"react-resizable-panels": "^2.1.7",
|
"react-resizable-panels": "^2.1.7",
|
||||||
"recharts": "2.15.0",
|
"recharts": "2.15.0",
|
||||||
"sharp": "^0.33.5",
|
|
||||||
"sonner": "^1.7.4",
|
"sonner": "^1.7.4",
|
||||||
"tailwind-merge": "^2.5.5",
|
"tailwind-merge": "^2.5.5",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"uuid": "^11.0.5",
|
|
||||||
"vaul": "^0.9.6",
|
"vaul": "^0.9.6",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
const backendPath = path.join(__dirname, '..', 'ember-market-backend');
|
|
||||||
const targetPath = path.join(__dirname, 'backend');
|
|
||||||
|
|
||||||
// Create backend directory if it doesn't exist
|
|
||||||
if (!fs.existsSync(targetPath)) {
|
|
||||||
fs.mkdirSync(targetPath, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to copy directory recursively
|
|
||||||
function copyDir(src, dest) {
|
|
||||||
// Create destination directory if it doesn't exist
|
|
||||||
if (!fs.existsSync(dest)) {
|
|
||||||
fs.mkdirSync(dest, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read contents of source directory
|
|
||||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
const srcPath = path.join(src, entry.name);
|
|
||||||
const destPath = path.join(dest, entry.name);
|
|
||||||
|
|
||||||
// Skip node_modules and .git directories
|
|
||||||
if (entry.name === 'node_modules' || entry.name === '.git') {
|
|
||||||
console.log(`Skipping ${entry.name}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
// Recursive call for directories
|
|
||||||
copyDir(srcPath, destPath);
|
|
||||||
} else {
|
|
||||||
// Copy file
|
|
||||||
fs.copyFileSync(srcPath, destPath);
|
|
||||||
console.log(`Copied: ${srcPath} -> ${destPath}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy files from backend to frontend/backend
|
|
||||||
try {
|
|
||||||
// Copy main backend directories
|
|
||||||
const dirsToSync = ['config', 'controllers', 'middleware', 'models', 'routes', 'scripts', 'utils'];
|
|
||||||
|
|
||||||
dirsToSync.forEach(dir => {
|
|
||||||
const sourcePath = path.join(backendPath, dir);
|
|
||||||
const destPath = path.join(targetPath, dir);
|
|
||||||
|
|
||||||
if (fs.existsSync(sourcePath)) {
|
|
||||||
copyDir(sourcePath, destPath);
|
|
||||||
} else {
|
|
||||||
console.warn(`Warning: Directory ${sourcePath} does not exist`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Copy .env file (you might want to modify this for different environments)
|
|
||||||
const envSource = path.join(backendPath, '.env');
|
|
||||||
const envDest = path.join(__dirname, '.env.backend');
|
|
||||||
|
|
||||||
if (fs.existsSync(envSource)) {
|
|
||||||
fs.copyFileSync(envSource, envDest);
|
|
||||||
console.log(`Copied: ${envSource} -> ${envDest}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Backend setup completed successfully!');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error setting up backend:', error);
|
|
||||||
}
|
|
||||||
247
test.ts
247
test.ts
@@ -1,247 +0,0 @@
|
|||||||
const wallets = [{
|
|
||||||
"walletName": "order_436f35e1085fcbad"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_2c9bbe4ae6c4eef6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_2af479fa96d55181"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_1dc02cf6d5515c74"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_a4a5f5ed3ede8907"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_7f90d78300af3d1f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_b07959c94030eb57"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_ea1dab8dc6ea3a9f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_784c47a3e75c0757"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_6e4a961a36489ed7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_022f32abeb8df016"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_5eb43e2ebf061eef"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_5564e8fc6cdd178f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_b903698054a946b7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_ec18ba3d2b841d1e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_cbdeecf081e7fca9"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_31bbce61f3086609"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_6fc27689e34665b7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_0913867abc1ac574"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_62b9c4078e73987a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_08ce3f3ecb52f951"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_168754ee60c498cc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_b260229ad465326d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_8b6ee943d834f6d9"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_7a66dda04b38f3d4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_f7c08834e0f2dd7e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_4f545ff25b60217c"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_abca6840cd07c802"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_0b833e1c4db24bc2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_0c237fe9bb7cd664"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_a317ad0f9ef453c1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_eb5179b2fcb03505"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_9ce17563c61e9596"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_a7590d44397eceb3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_88c8143c34efa91f"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_aae40e72084b4bcf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_d81c7b22222d57e8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_597141fc3d7d6c98"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_49ccc32e68c35843"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_e2961ed60392d07e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_a48546f981de5380"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_77d1bd8df8318e9e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_69706a17d6126c97"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_bafb24915caf828a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_d93635b18c3409eb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_03823e253b82c171"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_285d87cea8f684a6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_43550fea608097bf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_54bf9f7ab106cfca"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_c6d48e3b803115db"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_0bec1d36f2b315df"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_bcd511c30bbee158"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_1f91cc66630bba77"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_e11be5d3948106b9"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_d942ef659e5aa01a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_b6410c5daed33312"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_430143968de1a1f1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_0a46d56b27ff0bb2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_b0498d3c46b0eed8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_7ea739f584eff793"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_bc0166a8bc334f88"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_7e7b1c718ea579d4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_7c776972e4c04329"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_15eae822eb1ca3a2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_c57eae689ac827ab"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_162a8aefdee3934a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_79ff4f118bb49a46"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_a6d6e685cb93627d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_770c05f8f9aa3281"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_4eafb519b8b64129"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_533feb6a4843b162"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_40b640bfcaba6303"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_3de1a9cd802bc895"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_4b592780fc9c8e5a"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"walletName": "order_ba395cd8fba0239f"
|
|
||||||
}]
|
|
||||||
|
|
||||||
for (let wallet in wallets) {
|
|
||||||
const walletName = wallets[wallet].walletName
|
|
||||||
|
|
||||||
const auth = Buffer.from(`notiiwasntherexdddd:NYwsxePgMrThiapHnfCzUfaEfVlNKZECwvlqhHcWjerlZfcaTp`).toString('base64')
|
|
||||||
fetch(`http://152.53.124.126:9332/wallet/${walletName}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': `Basic ${auth}`
|
|
||||||
},
|
|
||||||
body: JSON.stringify({"jsonrpc": "1.0", "id": "curltest", "method": "getbalance", "params": ["*", 0]})
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(data)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error fetching wallet:', error)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user