Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,34 +1,60 @@
# ============================================
# Anchor API variables
# ============================================
# Base URL for anchor platform REST API (optional)
ANCHOR_API_BASE_URL=https://api.example.com/anchor

# ============================================
# Stellar / Soroban Network
# ============================================
# Target network: testnet or mainnet (optional, used by some utilities)
STELLAR_NETWORK=testnet
# Horizon server URL (optional, used by horizon helpers)
STELLAR_RPC_URL=https://soroban-testnet.stellar.org
# Soroban RPC endpoint for server-side calls (required for RPC features)
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
# Stellar network passphrase matching SOROBAN_RPC_URL (required)
SOROBAN_NETWORK_PASSPHRASE=Test SDF Network ; September 2015

# ============================================
# Contract IDs (Testnet placeholders)
# ============================================
INSURANCE_CONTRACT_ID=CACDYF3CYMJEJTIVFESQYZTN67GO2R5D5IUABTCUG3HXQSRXCSOROBAN
# Remittance split contract ID (optional)
REMITTANCE_SPLIT_CONTRACT_ID=CXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Savings goals contract ID (optional)
SAVINGS_GOALS_CONTRACT_ID=CXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Bill payments contract ID (optional)
BILL_PAYMENTS_CONTRACT_ID=CXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Insurance contract ID (optional)
INSURANCE_CONTRACT_ID=CXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Family wallet contract ID (optional)
FAMILY_WALLET_CONTRACT_ID=CXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Legacy or alternative variable names used by some modules (optional)
REMITTANCE_CONTRACT_ID=CACDYF3CYMJEJTIVFESQYZTN67GO2R5D5IUABTCUG3HXQSRXCSOROBAN
SAVINGS_CONTRACT_ID=CACDYF3CYMJEJTIVFESQYZTN67GO2R5D5IUABTCUG3HXQSRXCSOROBAN
BILLS_CONTRACT_ID=CACDYF3CYMJEJTIVFESQYZTN67GO2R5D5IUABTCUG3HXQSRXCSOROBAN

# ============================================
# Session Encryption (MUST be 32+ characters)
# Session / Auth Secrets
# ============================================
# Iron-session password (32+ chars) if using custom session
SESSION_PASSWORD=supersecurelongsessionpasswordatleast32characters!!
# NextAuth secret or generic session secret (optional, if using NextAuth or alt auth)
NEXTAUTH_SECRET=
SESSION_SECRET=

# ============================================
# Auth Secret (used in tests / API)
# ============================================
AUTH_SECRET=test-secret-for-local-dev-only

# ============================================
# Database configuration
# ============================================
# Database connection URL (Postgres/Prisma), or POSTGRES_URL alternative
DATABASE_URL=
POSTGRES_URL=

# ============================================
# Anchor Webhook Secret
# ============================================
Expand Down
61 changes: 35 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,36 +222,45 @@ All API routes are serverless functions deployed alongside the frontend.

### Environment Variables

Create a `.env.local` file in the root directory with the following variables:
Create a `.env.local` file in the root directory. See `.env.example` for a complete, documented list. Server-side configuration is centralized in [env.ts](file:///c:/Users/DELL/Desktop/Remitwise-Frontend/lib/env.ts).

```bash
# Stellar Network Configuration
NEXT_PUBLIC_STELLAR_NETWORK=testnet # or 'mainnet'
NEXT_PUBLIC_HORIZON_URL=https://horizon-testnet.stellar.org
NEXT_PUBLIC_SOROBAN_RPC_URL=https://soroban-testnet.stellar.org

# Contract IDs (deployed Soroban contracts)
NEXT_PUBLIC_REMITTANCE_SPLIT_CONTRACT_ID=
NEXT_PUBLIC_SAVINGS_GOALS_CONTRACT_ID=
NEXT_PUBLIC_BILL_PAYMENTS_CONTRACT_ID=
NEXT_PUBLIC_INSURANCE_CONTRACT_ID=
NEXT_PUBLIC_FAMILY_WALLET_CONTRACT_ID=

# Authentication
AUTH_SECRET=your-secret-key-here # Generate with: openssl rand -base64 32
SESSION_COOKIE_NAME=remitwise-session
SESSION_MAX_AGE=86400 # 24 hours in seconds

# API Configuration
API_RATE_LIMIT=100 # requests per minute
API_TIMEOUT=30000 # milliseconds

# Optional: Anchor Platform
ANCHOR_PLATFORM_URL=
ANCHOR_PLATFORM_API_KEY=
# Soroban RPC (required for on-chain features)
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
SOROBAN_NETWORK_PASSPHRASE=Test SDF Network ; September 2015

# Contract IDs (optional; required to enable specific features)
REMITTANCE_SPLIT_CONTRACT_ID=
SAVINGS_GOALS_CONTRACT_ID=
BILL_PAYMENTS_CONTRACT_ID=
INSURANCE_CONTRACT_ID=
FAMILY_WALLET_CONTRACT_ID=

# Database (optional; required if using the DB-backed features)
DATABASE_URL=
# or
POSTGRES_URL=

# Auth secrets (optional; required if using NextAuth or alt auth)
NEXTAUTH_SECRET=
SESSION_SECRET=

# Anchor API (optional; required if integrating an anchor)
ANCHOR_API_BASE_URL=
```

See `.env.example` for a complete list of configuration options.
Client-side variables for UI behavior continue to use the `NEXT_PUBLIC_*` prefix as needed.

Required variables by feature:
- Core Soroban connectivity: SOROBAN_RPC_URL, SOROBAN_NETWORK_PASSPHRASE
- Remittance split: REMITTANCE_SPLIT_CONTRACT_ID
- Savings goals: SAVINGS_GOALS_CONTRACT_ID
- Bill payments: BILL_PAYMENTS_CONTRACT_ID
- Insurance: INSURANCE_CONTRACT_ID
- Family wallet: FAMILY_WALLET_CONTRACT_ID
- Database-backed features: DATABASE_URL or POSTGRES_URL
- Anchor integrations: ANCHOR_API_BASE_URL
- NextAuth-based flows (if enabled): NEXTAUTH_SECRET or SESSION_SECRET

### API Middleware Configuration

Expand Down
41 changes: 41 additions & 0 deletions lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { z } from "zod";

const EnvSchema = z.object({
SOROBAN_RPC_URL: z
.string()
.default("https://soroban-testnet.stellar.org"),
SOROBAN_NETWORK_PASSPHRASE: z
.string()
.default("Test SDF Network ; September 2015"),
REMITTANCE_SPLIT_CONTRACT_ID: z.string().optional().default(""),
SAVINGS_GOALS_CONTRACT_ID: z.string().optional().default(""),
BILL_PAYMENTS_CONTRACT_ID: z.string().optional().default(""),
INSURANCE_CONTRACT_ID: z.string().optional().default(""),
FAMILY_WALLET_CONTRACT_ID: z.string().optional().default(""),
DATABASE_URL: z
.string()
.optional()
.default(process.env.POSTGRES_URL ?? ""),
POSTGRES_URL: z.string().optional().default(""),
NEXTAUTH_SECRET: z
.string()
.optional()
.default(process.env.SESSION_SECRET ?? ""),
SESSION_SECRET: z.string().optional().default(""),
ANCHOR_API_BASE_URL: z.string().optional().default(""),
});

const parsed = EnvSchema.parse(process.env);

export type Env = z.infer<typeof EnvSchema>;

export const env: Env = parsed;

export function requireEnv(keys: Array<keyof Env>): void {
for (const k of keys) {
const v = parsed[k];
if (typeof v === "string" && v.trim() === "") {
throw new Error(`Missing required environment variable: ${k as string}`);
}
}
}
10 changes: 5 additions & 5 deletions lib/soroban/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
*/

import { SorobanRpc, Networks } from "@stellar/stellar-sdk";
import { env } from "@/lib/env";

// ── Configuration ─────────────────────────────────────────────────────────────

const RPC_URL =
process.env.SOROBAN_RPC_URL ?? "https://soroban-testnet.stellar.org";
const RPC_URL = env.SOROBAN_RPC_URL ?? "https://soroban-testnet.stellar.org";

const NETWORK_PASSPHRASE =
process.env.SOROBAN_NETWORK_PASSPHRASE ?? Networks.TESTNET;
env.SOROBAN_NETWORK_PASSPHRASE ?? Networks.TESTNET;

/** How long (ms) to wait for a single RPC call before aborting. */
const TIMEOUT_MS = 10_000;
Expand All @@ -42,7 +42,7 @@ let _server: SorobanRpc.Server | null = null;
export function getServer(): SorobanRpc.Server {
if (!_server) {
_server = new SorobanRpc.Server(RPC_URL, {
allowHttp: RPC_URL.startsWith("http://"), // only allow plain HTTP for local dev
allowHttp: RPC_URL.startsWith("http://"),
});
}
return _server;
Expand Down Expand Up @@ -140,4 +140,4 @@ export class SorobanClientError extends Error {
this.name = "SorobanClientError";
this.cause = cause;
}
}
}