Skip to content

Payflowcore/payflowapp

Repository files navigation

Payflow on Stellar

Real payments, on Stellar.

Connect a Freighter wallet, send XLM and USDC on the Stellar testnet, and tip a Soroban smart contract — with an Express service layer and a React frontend.

Payflow is a non-custodial Stellar dApp. The backend never holds a secret key: it builds unsigned transactions, the browser signs them with Freighter, and the signed transaction is submitted to the network. Balances and history are read live from Horizon; the Tip Jar is a Soroban contract written in Rust.

Contents

What it does

  • Connect Freighter — your Stellar public key is your identity (no passwords).
  • Fund on testnet — one click funds a new account with Friendbot.
  • See live balances — XLM and USDC, read from Horizon.
  • Add a USDC trustline — sign a changeTrust transaction.
  • Send payments — build → sign in Freighter → submit a real on-chain XLM/USDC payment.
  • Review activity — payment history read from the ledger, with explorer links.
  • Tip a smart contract — call tip() / withdraw() on a Soroban Tip Jar.
  • Address book — save friendly labels for addresses (the only app-stored data).

Architecture

Browser (React)                 Express API                     Stellar testnet
─────────────────               ───────────────                 ────────────────
  Freighter  ──sign──┐          /api/tx/payment  ──build XDR──►  (unsigned)
                     │          /api/tx/submit    ──submit────►  Horizon / Soroban RPC
  build  ──────────► POST ────► /api/account/:pk  ──read──────►  Horizon
  request            │          /api/payments/:pk ──read──────►  Horizon
                     │          /api/tipjar/...    ──simulate──►  Soroban RPC
  signed XDR ────────┘

The signing key stays inside Freighter. The backend only ever sees unsigned XDR (to build) and signed XDR (to submit) — never a secret.

Stack

  • Backend: Node.js + Express, @stellar/stellar-sdk (Horizon + Soroban RPC)
  • Frontend: React + Vite + Tailwind, @stellar/freighter-api
  • Contract: Rust + soroban-sdk (the Tip Jar)
  • Storage: local JSON address book by default; Postgres when DATABASE_URL is set
  • Tests: Jest + Supertest (backend), cargo test (contract)

Repo layout

  • src/ — Express app, Stellar service layer (lib/stellar.js), routes, contacts model
  • frontend/ — React client (Freighter connect, balances, send, activity, tip jar)
  • contracts/tip-jar/ — the Soroban Tip Jar contract (Rust) + tests
  • tests/ — backend request tests (Horizon mocked, runs offline)
  • docs/ — maintainer notes and Wave issue ideas

Prerequisites

  • Node.js ≥ 18
  • The Freighter browser extension, set to Testnet
  • (Only to rebuild the contract) Rust + the Stellar CLI

Local setup

1. Install dependencies

npm install
cd frontend && npm install && cd ..

2. Configure environment

cp .env.example .env
cp frontend/.env.example frontend/.env

The defaults already target the Stellar testnet. Set TIPJAR_CONTRACT_ID once you've deployed the contract (see below). DATABASE_URL is optional — without it the address book uses a local JSON file.

3. Run it

# terminal 1 — API
npm run dev

# terminal 2 — frontend
cd frontend && npm run dev

Open the frontend, make sure Freighter is on Testnet, click Connect, then Fund with Friendbot — and send your first payment.

API summary

Method Path Purpose
GET /api/network Network config for the frontend
GET /api/account/:publicKey Balances + funded status (Horizon)
POST /api/account/:publicKey/fund Fund via Friendbot (testnet)
GET /api/payments/:publicKey Payment history (Horizon)
POST /api/tx/payment Build an unsigned payment XDR
POST /api/tx/change-trust Build an unsigned trustline XDR (USDC)
POST /api/tx/submit Submit a signed XDR (Horizon or Soroban RPC)
GET /api/tipjar/balance Read the Tip Jar contract balance
POST /api/tx/tip Build a tip() invocation
POST /api/tx/tip-withdraw Build a withdraw() invocation
GET/POST/DELETE /api/contacts... Address book CRUD

The Soroban Tip Jar

A small Rust contract that holds a token (the native XLM SAC). Anyone can tip(); only the owner can withdraw(). Build, test, and deploy instructions are in contracts/tip-jar/README.md. After deploying, set TIPJAR_CONTRACT_ID in .env and the Tip Jar page lights up. Running the app does not require Rust — only rebuilding the contract does.

Tests

npm test                              # backend (Horizon mocked — offline, fast)
cd contracts/tip-jar && cargo test    # the Soroban contract

Security notes

  • The backend is non-custodial — it never sees or stores a secret key.
  • All signing happens in Freighter; the API handles only unsigned/signed XDR.
  • This targets testnet. Do not point it at mainnet without a security review.
  • No secrets are logged; .env is git-ignored.

Contributing

See CONTRIBUTING.md. Issues are labelled for newcomers; the codebase is split into small, well-scoped areas (a route, a page, a contract function) to make first contributions easy.

Releases

No releases published

Packages

 
 
 

Contributors