YOUTUBE VIDEO LINK AT THE END
A Web3 full-stack application built for the Qie blockchain hackathon. QieRemit enables borderless financial transfers using the QUSD stablecoin.
- Framework: Next.js 14 (App Router) with TypeScript
- Styling: Tailwind CSS with glassmorphism effects
- Icons: Lucide React
- Database: MongoDB with Mongoose
- Blockchain: Ethers.js v6
- Smart Contracts: Solidity ^0.8.20
- Node.js 18+ and npm/yarn
- MetaMask or compatible Web3 wallet
- MongoDB Atlas account (or local MongoDB)
- Hardhat (for contract deployment)
Create a .env.local file in the root directory:
NEXT_PUBLIC_WALLET_CONNECT_ID=<placeholder>
MONGODB_URI=<your_mongodb_connection_string>
NEXT_PUBLIC_QSTABLE_CONTRACT_ADDRESS=<qusd_contract_address>
NEXT_PUBLIC_TREASURY_CONTRACT_ADDRESS=<treasury_contract_address>
PRIVATE_KEY=<your_wallet_private_key_for_deployment_OPTIONAL>
NEXT_PUBLIC_MOCK_ORACLE_ADDRESS=<mock_oracle_contract_address>
REDIS_URL=<redis_connection_string_or_local_host>
ANOMALY_SERVICE_URL=http://localhost:4000
ADMIN_DASHBOARD_WEBHOOK_URL=<optional_admin_alert_webhook>
QIEDX_PAIR=<optional_qiedex_pair_address>The application also reads config/config.json to determine the active network (default qieTestnet), RPC URLs, chain IDs, gas limits, and the placeholder qiedexPair. Update both .env.local and config/config.json together to switch between local, testnet, or future QIE deployments without editing individual files.
config/config.json keeps a small catalog of supported networks and their QIE endpoints (RPC, explorer, chain ID) along with a qiedexPair placeholder. The scripts and UI automatically read the active network, so you can add a new entry (e.g., a staging or QIE testnet with actual pair addresses) and select it via the DEFAULT_NETWORK env variable.
npm installThe contracts are located in the /contracts folder:
QUSD.sol- ERC20 stablecoin tokenQieTreasury.sol- Core treasury contract for swaps and transfers
Deployment Steps:
- Set up Hardhat (if not already done):
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
npx hardhat init- Install OpenZeppelin contracts:
npm install @openzeppelin/contracts-
Deploy contracts in this order:
- First deploy
QUSD.sol(owner should be your deployer address) - Then deploy
QieTreasury.sol(pass QUSD contract address and owner)
- First deploy
-
Update
.env.localwith the deployed contract addresses
npm run devOpen http://localhost:3000 in your browser.
- Modern, high-converting landing page
- "Launch App" button that connects wallet and redirects to dashboard
- Wallet Connection: Connect MetaMask/Web3 wallet
- Balance Display: Shows native QIE and QUSD balances
- KYC Verification: Simulated KYC check that saves to MongoDB
- Swap QIE for QUSD: Deposit native QIE and receive QUSD tokens
- Send Globally: Execute cross-border transfers with target currency selection
- Paginated Ledger: Server-side transaction history sourced from on-chain events
- Data Rights Controls: Export/delete off-chain profile data instantly
- Mock QIE Oracle + Currency Converter: The dashboard polls
MockQieOracle(deploy viascripts/deploy-all.js) and re-sizes FX rates for every currency card; update the price in one command withnpm run mock:oracle 1.05during demos. - Redis-backed Queue: The listener enqueues every cross-border swap into Redis before persisting to Mongo, so temporary Mongo outages donβt drop events.
- QIEDEX Simulation:
scripts/deploy-all.jsdeploysMockQieDexand runs a representative swap to show how future QIEDEX integrations can be wired in.
qiehack/
βββ contracts/ # Solidity smart contracts
β βββ QUSD.sol
β βββ QieTreasury.sol
βββ app/ # Next.js App Router
β βββ api/ # API routes
β β βββ db/connect/ # MongoDB connection helper
β β βββ user/ # User KYC endpoints
β βββ dashboard/ # Main dashboard page
β βββ layout.tsx # Root layout with providers
β βββ page.tsx # Landing page
βββ contexts/ # React contexts
β βββ Web3Provider.tsx # Web3 wallet integration
βββ lib/ # Utilities
β βββ mongodb.ts # MongoDB connection
β βββ web3.ts # Web3 helpers
βββ package.json
-
Our anomaly detection system mimics real-world fintech/Web3 risk engines by combining:
- browser fingerprinting
- IP reputation scoring
- wallet behavior analysis
- rule-based fraud heuristics
-
Using
- β FingerprintJS (open-source)
- β AbuseIPDB API
- β Rule-based anomaly engine
-
API middleware: New Next.js proxy routes under
/api/anomaly/*forward client telemetry toanomaly-engine, normalize fingerprint data, and expose hooks for the dashboard (/event,/alerts,/fingerprint,/webhook/status,/webhook/test). The client-side helper inlib/anomaly.tsenriches every swap/send with fingerprint metadata, caches the verdict, and feeds the risk monitor card on the dashboard plus badges inside the transaction history list. -
UI surface: Each ledger entry now shows an anomaly badge, the dashboard risk monitor card displays the latest verdict, and
/dashboard/adminsummarizes queue alerts, shows verdict reasons, and lets you ping the configured webhook. A dedicated worker (anomaly-engine/workers/alertWorker.js, runnable vianpm run worker) listens on Redis and posts high-risk hits toADMIN_DASHBOARD_WEBHOOK_URL.
- Standard ERC20 token
- Mintable/burnable by owner (Treasury contract)
- Name: "Qie Stable USD", Symbol: "QUSD"
depositNativeForStable(): Swap native QIE for QUSD (1:1 rate)executeCrossBorderTransfer(): Burn QUSD and emit event for off-chain processing- Owner can withdraw native QIE
Run the lightweight relayer to mirror on-chain CrossBorderFulfillmentRequested and NativeDeposited
events into MongoDB for compliance, dashboards, and off-chain fulfillment queues.
- Configure the following in
.env.local(or your shell):QIE_RPC_URL=https://rpc-main1.qie.org # Optional websocket endpoint for realtime updates QIE_WS_RPC_URL=wss://rpc-main1.qie.org/ws NEXT_PUBLIC_TREASURY_CONTRACT_ADDRESS=<treasury_address> - Run the listener:
The listener enqueues everything into Redis (
npm run listener
REDIS_URLin.env.local). You can point it to a local Redis instance (e.g.,docker run -p 6379:6379 redis) or any hosted queue to smooth over short outages. - The script performs a historical sync, then listens for new events, persisting them in the
TransferEventcollection with live status updates.
Use the /api/transfers endpoint (GET with address, page, limit) to power dashboards or audit tools.
Trigger a manual sync by POSTing to the same route (optionally pass fromBlock/toBlock).
Use npm run mock:oracle <price> to bump the mocked FX feed and watch the Currency Converter + swap flows update instantly.
scripts/deploy-all.jsdeploysMockQieOracleandMockQieDex, prints their addresses, and even runs one mock swap so judges can see the QIEDEX flow without needing a real pair.MockQieOraclepowers the UI rate badge and the converter input. Update it during a demo withnpm run mock:oracle 1.05(or any price) and the dashboard immediately reflects the change.- The config-driven
qiedexPairentry behaves as an anchor for a future real QIEDEX testnet pairβreplace the placeholder address inconfig/config.jsonwith the official pair and the scripts will log/approve swaps against that contract instead of the mock.
- The Next.js app and the anomaly middleware each ship with their own
Dockerfile. The rootDockerfileruns a multi-stage build (npm ci,npm run build,npm run start), whileanomaly-engine/Dockerfileboots the Express/Redis listener. Both containers read the same environment variables outlined above (plusANOMALY_SERVICE_URLpointing athttp://anomaly-engine:4000). docker-compose.ymlties the frontend, anomaly service, alert worker (npm run worker), Redis, and MongoDB together. All web traffic flows through the Next app, which uses/api/anomaly/*routes to talk to the middleware and shares the Redis queue URL with the worker so webhooks fire in real time.- To launch everything locally:
- Add the usual
.enventries (contracts, Mongo/Redis URLs,ADMIN_DASHBOARD_WEBHOOK_URL, etc.). - Run
docker compose up --buildfrom the repo root. - The Next app is available on
http://localhost:3000, the middleware onhttp://localhost:4000, and the admin panel lives at/dashboard/admin.
- Add the usual
Use docker compose down to stop the stack, or run npm run worker inside the anomaly-engine folder for ad-hoc webhook processing without Compose.
- Run
npx hardhat testto cover the treasury flow plus the mock oracle sanity checks. The suite now exercisesMockQieOracleso you can prove the mock feeds are trustworthy. - Re-run
npm run listenerduring local testing to ensure Redis-backed queue processing keeps theTransferEventledger aligned even if Mongo briefly goes offline.
Set the following in .env.local:
NEXT_PUBLIC_QSTABLE_CONTRACT_ADDRESS=<QUSD address>
NEXT_PUBLIC_TREASURY_CONTRACT_ADDRESS=<Treasury address>
QIE_RPC_URL=https://rpc1mainnet.qie.digital
QIE_CHAIN_ID=1990
QIE_EXPLORER_URL=https://mainnet.qie.digital
DEFAULT_NETWORK=qie
MONGODB_URI=<MongoDB Atlas URI>
REDIS_URL=<Upstash Redis URL>
ANOMALY_SERVICE_URL=http://localhost:4000
Set the following in .env for Node scripts:
MONGODB_URI=<same as above>
REDIS_URL=<same as above>
QIE_RPC_URL=https://rpc1mainnet.qie.digital
QIE_CHAIN_ID=1990
QIE_EXPLORER_URL=https://mainnet.qie.digital
DEFAULT_NETWORK=qie
NEXT_PUBLIC_TREASURY_CONTRACT_ADDRESS=<Treasury address>
NEXT_PUBLIC_QSTABLE_CONTRACT_ADDRESS=<QUSD address>
- Frontend:
npm run dev - Anomaly middleware:
cd anomaly-engine && npm start - Cross-border listener:
npm run listener - Oracle feeder:
npx tsx scripts/oracle-feeder.ts
- Overview
/admin: Treasury balances, throughput, risk summary, explorer link - Ledger
/admin/ledger: Transaction table with explorer links and a βSync Nowβ button that triggers/api/transfersPOST to backfill events from chain
- New users must complete KYC before using Swap or Global Send
- The Dashboard shows an βIdentity Verificationβ card linking to Blockpass:
https://verify-with.blockpass.org/?clientId=financial_app_00065
- The UI disables Swap and Send, shows a banner, and enforces checks in handlers until KYC is verified
- Verification status is read via
/api/user?address=<wallet>; after success,POST /api/userwith{ walletAddress }marksisKycVerified=true
- Explorer links not opening: verify
QIE_EXPLORER_URLand contract addresses - Admin not updating: ensure anomaly middleware and listener are running, then use βSync Nowβ
- Wallet balances not reading: confirm wallet switched to QIE chain (1990) in MetaMask
- See
DEMOS.mdfor the recommended Loom flow (wallet connect, mock oracle tuning, cross-border swap, queue output, and QIEDEX simulation). Follow the checklist to narrate how each component maps to the βDeFi Without Bordersβ story.
- Dark fintech theme (slate-950 background)
- Blue/cyan gradient accents
- Glassmorphism effects
- Responsive design
- Toast notifications for user feedback
- Loading states for all async operations
- Contract addresses must be set in
.env.localbefore using swap/send features - MongoDB connection is cached to prevent cold start issues
- KYC is simulated for hackathon purposes
- Cross-border transfers emit events that would be processed by an off-chain oracle in production
Built for Qie Hackathon 2025 https://youtu.be/W1ehS7JrYpM