Inspiration
Freelancers lose too much time chasing payments — and when a payment is disputed, the proof is a screenshot or an email that can be edited or lost. We wanted a receipt that cannot be faked: an invoice that comes back from the dead as an on-chain NFT. PayPhantom builds on our earlier PayPilot project, which proved that a chat message can become a real PayPal invoice.
What it does
Type a billing request in plain Indonesian or English and Gemini parses it into a structured invoice. PayPal sends it, the client pays it through the payment link, and the moment it is paid PayPhantom records a receipt. The receipt is then minted as an ERC-721 NFT on BNB Chain, with the PayPal invoice id, payer, amount, currency and paid time in its on-chain metadata.
Because the operator wallet holds very little BNB, minting is deferred and operator-confirmed by design: the receipt is recorded first (PENDING), and the chain mint happens only when the operator confirms it and the wallet can afford gas. The server never signs anything. A mock mode runs the whole story with zero credentials and zero BNB.
How we built it
We planned it in Kiro first — requirements, design and tasks in .kiro/specs/payphantom/, with steering docs, agent hooks and an MCP server (see "How Kiro was used" below). The app is Node 24 + Express 5: Gemini (gemini-3.6-flash) parses the chat, the PayPal Invoicing API v2 (sandbox) creates and sends the invoice, and the receipt contract is Solidity + OpenZeppelin, compiled with Foundry. The mint cost is quoted live from a public BSC RPC (about 150,000 gas x 0.05 gwei, roughly 0.000008 BNB).
Challenges we ran into
Gemini's free tier ran out the same morning we recorded the demo (HTTP 429), then the model itself was overloaded (HTTP 503) in the afternoon — the demo only became possible after it recovered in the evening. PayPal Invoicing rejects IDR, so the live demo uses USD. Mock-pay works only in mock mode, so a live paid flip needs a real sandbox buyer account. And the operator wallet holds only about 0.000351 BNB, which forced the deferred-mint design instead of minting on every payment.
Accomplishments that we're proud of
Two real sandbox invoices created and sent live from a chat message (Sarah, $120 USD, status SENT). A 53-second demo video recorded and published. A public repo with an MIT license and /.kiro at root. 4,000 free Kiro credits redeemed for the build.
What we learned
Currency support is a real constraint, not a detail. Free-tier AI can be so slow that the client times out even though the invoice was created. And designing for a nearly empty wallet — record first, mint on confirmation — is more honest than pretending gas is free.
What's next for PayPhantom
A real sandbox payer completing a live paid flip, deploying the receipt contract to BNB Chain, a payer-funded mint option, and more invoice currencies wherever PayPal allows them.
How Kiro was used
- Specs: requirements, design and tasks in
.kiro/specs/payphantom/were written before any code; implementation followedtasks.md. - Steering:
.kiro/steering/holds product, tech, structure and security docs that are always on — the security file is why the public repo contains zero credentials. - Agent hooks:
.kiro/hooks/quality-gates.jsonrunsnode --checkon every saved.jsfile and reminds the agent to run tests and check for staged secrets. - MCP: a local stdio MCP server (
scripts/mcp-payphantom.mjs) exposesreceipt_gas_quote, pricing a receipt mint from public BSC RPC without keys or signing. - Kiro CLI: version 3.3.0, installed from
cli.kiro.dev; sessions run withkiro-cli chatinside the repo so specs, steering, hooks and MCP all apply.
Built With
- bnb-chain
- erc-721
- express.js
- foundry
- gemini
- javascript
- kiro
- node.js
- openzeppelin
- paypal
- solidity