FlowPaydocs

What is FlowPay?

ETHGlobal NYC 2026

FlowPay is an intent-based cross-chain payment engine. You describe a payment in plain language — who, how much, in what token, and why — and FlowPay parses the intent, resolves names, builds a cross-chain route, executes settlement on Hedera, and records a permanent audit trail.

No wallet switching. No chain selection. No gas guessing. One sentence.

Example intent

"Send 200 USDC from María to Juan in Mexico for rent"

→ Parsed by Google Gemini 2.0 Flash
→ Juan resolved via ENS (juan.eth) or demo registry
→ Cross-chain route built by LI.FI Composer SDK
→ Settled on Hedera (< 3s, $0.001)
→ Audit record written to HCS topic 0.0.9217982
FlowPay is a UX and settlement layer — not a protocol. It composes Google Gemini, LI.FI, and Hedera into a single user interaction.

Quickstart

Run FlowPay locally in under 5 minutes.

1

Clone & install

git clone https://github.com/riesgopais/flowpay
cd flowpay
npm install
2

Configure environment

cp .env.example .env.local
# Fill in GOOGLE_API_KEY, HEDERA_ACCOUNT_ID,
# HEDERA_PRIVATE_KEY, LIFI_API_KEY
3

Run dev server

npm run dev
# Open http://localhost:3000
If GOOGLE_API_KEY is absent, the fallback regex parser activates automatically. The demo still works without any API keys for basic testing.

Payment pipeline

Every payment goes through four sequential steps, streamed in real time via Server-Sent Events.

01

Intent parsing — Google Gemini

Gemini 2.0 Flash parses the plain language input using Structured Outputs (responseMimeType: application/json + responseSchema). Returns a fully typed PaymentIntent object. The hybrid parser checks a keyword fast-path first — Gemini is only called for ambiguous intents.

02

Route building — LI.FI Composer

LI.FI Composer SDK builds an atomic cross-chain EVM flow. Same token → direct transfer. Different tokens → swap via aggregator. Returns a compiled transactionRequest ready for wallet signing.

03

Settlement — Hedera HBAR

A native HBAR TransferTransaction executes on Hedera Testnet from the relayer account. 0.001 HBAR for EVM token payments, up to 1 HBAR for HBAR-native payments. Finality in < 3 seconds.

04

Audit record — Hedera HCS

A TopicMessageSubmitTransaction writes the full payment intent to HCS topic 0.0.9217982. Includes status: SUCCESS | ROUTING_FAILED | PAYMENT_FAILED. HCS only writes SUCCESS after the HBAR payment confirms — atomicity guaranteed.

Hybrid intent parser

FlowPay uses a two-stage parser to minimize latency and API costs while maintaining accuracy.

⚡ Keyword engine

Deterministic regex parser. Returns HIGH confidence when intent contains an explicit amount + token + known recipient. No AI call. Instant response.

When to use: "Send 100 USDC to Sofia for rent"

🤖 Gemini 2.0 Flash

Called only when the keyword engine returns LOW confidence: missing amount, ambiguous phrasing, complex multi-clause sentences, or unknown constructs.

When to use: "Maybe send some funds to my friend in Mexico"

The confirmation card shows a badge: ⚡ instant when the keyword engine resolved the intent, or AI-assisted when Gemini was invoked.

Name resolution & ENS

New

FlowPay resolves human names to wallet addresses in two stages, in order:

1
Demo registryinstant

14 hardcoded names (ES + EN) with testnet EVM and Hedera addresses. Instant — no network call.

2
ENS on Ethereum mainneton-chain

If name not in registry, resolves via viem.getEnsAddress(). Accepts "vitalik" (auto-appends .eth) and "nick.eth" (explicit). Returns null if not found → 422.

Resolution examples

"Send 100 USDC to Sofia"     → registry   → 0x742d35… (instant)
"Send 100 USDC to vitalik"   → ENS lookup → vitalik.eth → 0xd8dA6B…
"Send 100 USDC to nick.eth"  → ENS lookup → nick.eth    → 0xb8c2C8…
"Send 100 USDC to Roberto"   → registry miss → ENS miss → 422
ENS resolution uses Ethereum mainnet. Ensure ETHEREUM_RPC_URL is set for production use, or the default Cloudflare public endpoint will be used (may rate-limit under heavy traffic).

HCS atomicity

The audit record on Hedera Consensus Service reflects actual payment outcome — never a false positive.

SUCCESSWritten only after the HBAR TransferTransaction confirms on-chain.
ROUTING_FAILEDWritten if LI.FI Composer fails to build or compile the cross-chain flow.
PAYMENT_FAILEDWritten if the HBAR transfer itself fails after routing succeeded.
HCS records are publicly verifiable at hashscan.io/testnet/topic/0.0.9217982

POST /api/parse

Parses a natural language intent and returns a structured preview for user confirmation. Does not execute any blockchain transaction.

Request

{
  "intent": "Send 100 USDC to Sofia for rent"
}

Response (200)

{
  "amount": 100,
  "fromToken": "USDC",
  "toToken": "USDC",
  "recipientAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
  "hederaRecipient": "0.0.98",
  "senderName": null,
  "recipientName": "Sofia",
  "memo": "rent",
  "humanSummary": "Send 100 USDC to Sofia for rent",
  "error": null,
  "_parsedBy": "keyword",
  "warnings": ["Sending to Sofia's registered testnet address"],
  "resolvedAddressLabel": "Resolved from demo registry"
}
errorNon-null when intent cannot be processed: unsupported token, invalid amount, ambiguous input.
_parsedBy"keyword" when the fast-path engine resolved it. "gemini" when AI was invoked. "fallback" when no API key is present.
warnings[]Array of AI assumption warnings shown to the user before confirmation: defaulted amount, defaulted token, ENS/registry resolution notice.
resolvedAddressLabelHuman-readable source of address resolution: "Resolved via ENS (sofia.eth)" or "Resolved from demo registry".
400 for empty or missing intent. Unsupported tokens (BTC, SOL, XRP…) return 200 with error field set, not a 4xx — the frontend reads the field to show the error in-context.

POST /api/pay-stream

Executes a payment and streams real-time progress via Server-Sent Events. Each event corresponds to an actual backend step completing — no fake delays.

Request

{
  "intent": "Send 100 USDC to Sofia for rent",
  "senderAddress": "0x..."   // optional — enables on-chain wallet signing
}

SSE stream

data: {"type":"step","index":0}         // Gemini parsed
data: {"type":"step","index":1}         // LI.FI route built
data: {"type":"step","index":2}         // HBAR settlement executed
data: {"type":"step","index":3}         // HCS audit record written

data: {
  "type": "done",
  "data": {
    "success": true,
    "parsed":  { "humanSummary": "...", "amount": 100, ... },
    "lifi":    { "flowBuilt": true, "steps": [...], "compiled": true },
    "hcs":     { "topicId": "0.0.9217982", "sequenceNumber": "42",
                 "explorerUrl": "https://hashscan.io/testnet/topic/0.0.9217982" },
    "payment": { "transactionId": "0.0.9185784@1749812345.000000000",
                 "amount": "0.001 HBAR",
                 "explorerUrl": "https://hashscan.io/testnet/transaction/..." }
  }
}

// On error:
data: {"type":"error","error":"STAGING_LIQUIDITY_DRY",
       "message":"Staging liquidity pool dry — try matching tokens (USDC→USDC).",
       "status":500}
400Empty or missing intent.
422Unsupported token · amount ≤ 0 · unknown name with no explicit address.
500 ROUTING_FAILEDLI.FI Composer failed to build or compile the route. HCS records ROUTING_FAILED.
500 PAYMENT_FAILEDHBAR transfer failed. HCS records PAYMENT_FAILED.
The frontend uses a 25-second per-step watchdog via AbortController. If no SSE event arrives for 25s, the request is aborted and the user sees Network congestion detected — please retry.

Google Gemini 2.0 Flash

Used as the NL parsing layer. Called only when the keyword engine returns low confidence.

Modelgemini-2.0-flash via @google/generative-ai
Structured OutputsresponseMimeType: 'application/json' + responseSchema. No prompt engineering for JSON format — the schema enforces structure.
Single-token ruleIf user mentions one token, both fromToken and toToken are set to that token. No invented swap.
Fallbackregex-based fallbackParse() activates when GOOGLE_API_KEY is absent. Demo-safe.

LI.FI Composer SDK

Builds atomic cross-chain EVM payment flows. ETHGlobal staging endpoint.

Endpointethglobal-composer.li.quest (ETHGlobal-specific staging)
toWei()Handles decimals: USDC/USDT=6, ETH/WETH/DAI=18, WBTC=8.
Staging limitsPools can be dry for cross-token swaps. Use matching tokens (USDC→USDC) for reliable demo runs.

Hedera HCS + HBAR

Zero Solidity. All Hedera interaction via native @hashgraph/sdk.

HCS Topic0.0.9217982 — public, immutable, verifiable on Hashscan.
HBAR operator0.0.9185784 — the FlowPay relayer account. Pays all transaction fees.
Settlement amount0.001 HBAR for EVM token payments (settlement signal). Up to 1 HBAR for HBAR-native payments.
Finality< 3 seconds. Fixed USD fee ~$0.001. No variable gas.

ENS via viem

ENS resolution runs on Ethereum mainnet via viem.getEnsAddress().

RPCConfigurable via ETHEREUM_RPC_URL. Defaults to https://cloudflare-eth.com.
normalize()viem/ens normalize() applied before lookup — handles unicode names correctly.
Auto-suffixPlain names auto-append .eth. "vitalik" → resolves as "vitalik.eth".
Production pathSwap hardcoded registry for full ENS + Hedera Name Service lookup.

Supported tokens

TokenDecimalsNotes
ETH / WETH18
USDC6
USDT6
DAI18
WBTC8Capped at 0.01 in demo
HBARNative Hedera, up to 1 HBAR
MATIC / POL18
BTC, SOL, XRP, ADA…Returns 422 — not supported

Use cases

Remittances

Send money home to family in plain language. No exchange account, no FX margin, no wire delays.

Freelance payroll

Pay global contractors in their preferred token. One sentence, cross-chain, permanent audit record.

School fees

International tuition without wire transfers or 3–5% conversion margins.

DAO payouts

Coordinate multi-chain treasury distributions with a tamper-proof audit trail on HCS.

AI agent payments

Autonomous agents can execute payments via a single API call. Intent in → settlement out.

B2B invoicing

Enterprise-to-enterprise cross-border payments with immutable proof of execution.

FAQ

Is this using real funds?

No. FlowPay runs on Hedera Testnet. HBAR transferred has no real monetary value. LI.FI routes are compiled but the wallet signing step is optional and not submitted to mainnet in the demo flow.

Why does FlowPay use Gemini instead of other AI models?

Gemini 2.0 Flash offers Structured Outputs (responseMimeType + responseSchema) which enforces a typed PaymentIntent without prompt engineering for JSON formatting. This is more reliable than asking any model to "return JSON". Also: ETHGlobal Google Cloud track.

What is the keyword engine and when does it skip Gemini?

lib/keyword-parser.ts runs first on every intent. If it finds an explicit amount + token + known recipient (registry name or 0x address), it returns HIGH confidence and the result is used directly. Gemini is never called. For ambiguous or incomplete intents, the keyword engine returns LOW confidence and Gemini handles it.

How does ENS resolution work?

lib/resolver.ts checks the mock registry first (instant). If the name is not found there, it calls viem.getEnsAddress() on Ethereum mainnet. Plain names like "vitalik" are auto-suffixed to "vitalik.eth". If ENS also returns null, the API returns 422 and the UI shows an address input field.

What happens if LI.FI staging has no liquidity?

The SSE stream emits { type: "error", error: "STAGING_LIQUIDITY_DRY" } with a human-readable message suggesting the user try matching tokens (USDC→USDC instead of ETH→USDC). The HCS record is written as ROUTING_FAILED.

Can I run this with my own Hedera account?

Yes. Clone the repo, fill in HEDERA_ACCOUNT_ID and HEDERA_PRIVATE_KEY (ECDSA) in .env.local, and run npm run dev. Leave HEDERA_TOPIC_ID blank on first run — a new HCS topic is auto-created.

What does "No Solidity" mean?

FlowPay uses Hedera's native @hashgraph/sdk for everything: TransferTransaction for HBAR, TopicMessageSubmitTransaction for HCS. No EVM bytecode, no compiled contracts, no Solidity.

Built at ETHGlobal New York 2026