CupTreasury is a self-custodial football team treasury for squads, fan groups, and tournament teams. It helps a team collect contributions, approve match-day expenses, turn approvals into exact WDK-guarded PaymentIntent capabilities, and prepare safe no-broadcast receipts.
The semifinal proof is WDK-native guarded execution: WDK independently binds and signs the exact approved transaction, while a local-only TeamTreasury contract independently enforces Captain/Treasurer approval rules. The deterministic local proof transfers exactly 120000000 atomic MockUSDT (120 six-decimal units) to the recipient. MockUSDT is a local test token and is not official USDt.
Live demo: https://cuptreasury.vercel.app/
Repository: https://github.com/alsaecas/cuptreasury
- Nation: Spain
- Location: Valencia, Spain
- Hackathon: Tether Developers Cup
- Primary track: WDK only
- Secondary track: none
- License: Apache 2.0
WDK verification:
- Guarded execution page: https://cuptreasury.vercel.app/guarded-execution
- WDK proof page: https://cuptreasury.vercel.app/wdk-proof
- CLI:
npm run wdk:smoke - Policy proof:
npm run wdk:policy-demo - Full local verification:
npm run semifinal:verify - CI:
Selected track: WDK only. QVAC is not claimed. Pear is not claimed.
Real:
@tetherto/wdk@1.0.0-beta.13@tetherto/wdk-wallet-evm@1.0.0-beta.15- WDK native account-scoped transaction policy registration
- WDK native
account.simulate.signTransaction(...)ALLOW/DENY decisions with trace - Provider-derived unsigned transaction fields for the prepared calldata
- Honest WDK fee-quote status; placeholder-token quotes may be unsupported
- WDK no-broadcast transaction signing
- Application-owned one-time PaymentIntent consumption
- Sanitized proof artifacts in CI
Browser:
- Visualizes the guarded execution proof and local treasury flow.
- Does not execute native WDK wallet operations.
- Does not sign or broadcast browser treasury payments.
- Keeps wallet secrets out of React state and localStorage.
- Open
/guarded-execution. - Skim this README architecture summary.
- Run or inspect
npm run wdk:policy-demo.
- Read
docs/SEMIFINAL_REVIEW.mdafter the pinned-link commit is created. - Review
src/domain/treasury/**. - Review
src/lib/wdk/guarded/**. - Inspect CI proof artifacts from GitHub Actions.
- Read
docs/ARCHITECTURE.md. - Read
docs/SECURITY_MODEL.md. - Read
docs/WDK_API_RESEARCH.md. - Review ADRs in
docs/adr/.
Grassroots football teams often manage shared money in WhatsApp: contribution reminders, receipt screenshots, away match travel, team dinners, ticket pools, kit, equipment, and tournament registration. That gets messy fast.
CupTreasury gives the squad one browser-based treasury view:
- Who paid and who still owes squad contributions
- Which match-day expenses are pending
- Captain and Treasurer approval flow
- WDK-guarded PaymentIntent capability boundary
- Local assistant answers from local treasury data
- In-app WDK verification and guarded execution proof pages
The demo squad is Valencia Hackers FC at the Tether Developers Cup.
- Polished landing page,
/treasuryjudge flow, and/guarded-execution - In-app WDK proof verification at
/wdk-proof - API endpoint at
/api/wdk/smoke(returns honest status; WDK native addons prevent Vercel execution) - Valencia Hackers FC treasury dashboard
- Member roles: Captain, Treasurer, Player, Fan
- Contribution status: Paid, Pending, Partial
- Payment requests for football/tournament expenses
- Local deterministic risk note for new requests
- Approval rules:
- Above 100 USDt requires two approvals
- 100 USDt or below requires one approval
- Only Captain and Treasurer can approve/reject
- PaymentIntent domain model and approval policy tests
- Payment policy card displaying live rule application
- Safe no-broadcast receipt preparation after approvals
- WDK wallet/payment panel with honest Node/CI boundary status
- Local deterministic assistant for treasury questions
- Squad Reminder generator with copy-to-clipboard
- localStorage persistence and reset demo data
WDK integration files:
src/lib/wdk/wdkTreasuryAdapter.ts— browser adapter boundarysrc/lib/wdk/wdkSmokeVerification.ts— shared server-side smoke logicsrc/lib/wdk/guarded/**— guarded PaymentIntent WDK policy pipelinescripts/wdk-smoke-test.ts— CLI smoke test entry pointscripts/wdk-policy-demo.ts— ALLOW/DENY policy proof entry pointsrc/app/api/wdk/smoke/route.ts— in-app API endpointsrc/app/guarded-execution/page.tsx— guarded execution proof routesrc/components/wallet/WdkWalletPanel.tsx— treasury WDK panelsrc/components/wallet/WdkProofClient.tsx— WDK proof page UIsrc/app/wdk-proof/page.tsx— WDK proof route
The adapter exposes:
getAdapterStatus()getTreasuryWallet()getBalance()preparePayment()executePayment()getExplorerUrl()
What is real:
@tetherto/wdkis installed.@tetherto/wdk-wallet-evmis installed.scripts/wdk-smoke-test.tsperforms a no-funds Node smoke test.scripts/wdk-policy-demo.tsperforms native WDK policy simulation for exact PaymentIntent signing.- The shared module
src/lib/wdk/wdkSmokeVerification.tsis used by both the CLI smoke test and the API route. - The smoke test generates an ephemeral seed phrase, registers an EVM wallet module, derives an account, reads Sepolia native balance through a public RPC, quotes a zero-value transaction fee, signs a message, verifies the signature, and disposes the WDK instance.
- The policy demo creates a 120-token van-rental request, validates approvals against a trusted roster, denies one approval, allows the exact two-approval intent, denies changed amount, recipient, token, chain, account, expiry, and replay changes, signs the exact no-broadcast transaction once, and writes sanitized JSON proof.
- The live app includes a
/wdk-proofpage that explains WDK verification methods and links to the CLI smoke test. - The live app includes
/guarded-executionto visualize the guarded proof and browser/Node boundary. - The
/api/wdk/smokeendpoint is a serverless compatibility check that reportsunsupported_runtimebecause WDK's sodium-native addon cannot be bundled for Vercel's serverless runtime. - GitHub Actions run lint, build, tests, generated fixture checks, WDK smoke proof, WDK policy proof, and sanitized artifact upload.
Run:
npm run wdk:smoke
npm run wdk:policy-demo
npm run contract:test
npm run wdk:contract-demo
npm run wdk:contract-demo:json
npm run contract-proof:check
npm run semifinal:verifyOpen in-app:
https://cuptreasury.vercel.app/guarded-execution
What remains browser-only:
- Browser treasury payment execution is not claimed.
- Native WDK wallet operations run in Node/CI, not in Vercel browser UI.
- No real token transaction is broadcast by default.
- The dashboard balance is local demo state, not a live treasury balance.
- The demo wallet address is a placeholder.
- No seed phrase, private key, or real wallet material is stored in React state or localStorage.
Why this matters:
The app now demonstrates real WDK package installability, native transaction-policy evaluation, exact PaymentIntent capability binding, application-owned one-time consumption, provider-derived unsigned transaction fields, and no-broadcast signing without risking secret handling in the deployed browser MVP. Production payment execution still needs durable transactional storage, secure key custody, real token contract configuration, testnet funds, explicit broadcast controls, and explorer tracking.
See:
docs/ARCHITECTURE.mddocs/SECURITY_MODEL.mddocs/WDK_API_RESEARCH.mddocs/WDK_INTEGRATION_NOTES.mddocs/TRACK_COMPLIANCE.md
QVAC is not claimed as a completed track in this build.
The local assistant boundary lives in:
src/lib/qvac/qvacTreasuryAssistant.ts
Current status: local deterministic assistant and QVAC-ready adapter shape.
It supports:
- Summarize treasury
- Who still owes money
- Detect unusual expenses
- Generate Squad Reminder (WhatsApp-style message with copy button)
- Explain pending approvals
The current app does not run @qvac/sdk, local model inference, embeddings, RAG, speech, multimodal inference, remote inference, or any cloud AI API.
CupTreasury is intentionally not a generic crypto wallet. It is shaped around:
- Away match travel
- Tournament registration
- Team dinner after match
- Kit and equipment
- Match tickets
- Prize pool
- Fan group wallet
- Watch-party expenses
- Squad contribution reminders
- Captain and Treasurer approvals
No real club logos, FIFA/UEFA marks, player images, or copyrighted football assets are used.
Package manager: npm.
npm install
npm run devOpen:
http://localhost:3000
Checks:
npm run lint
npm run build
npm test
npm run test:coverage
npm run wdk:smoke
npm run wdk:policy-demo
npm run wdk:policy-demo:jsonThe browser demo requires no environment variables.
Optional smoke-test overrides:
WDK_SMOKE_EVM_RPC_URL=https://sepolia.drpc.org
WDK_SMOKE_EVM_CHAIN_ID=11155111- Open https://cuptreasury.vercel.app/
- Open the Valencia Hackers FC treasury.
- Review balance, members, pending contributions, and payment requests.
- Create a match-day expense.
- Approve it as Captain or Treasurer.
- Check the Treasury Policy card for live rule application.
- Prepare a safe no-broadcast receipt.
- Open /guarded-execution and review the WDK policy proof.
- Open /wdk-proof and review the WDK smoke path.
- Ask the local assistant: "Who still owes money?" or use "Generate Squad Reminder".
src/
app/
page.tsx
guarded-execution/page.tsx
treasury/page.tsx
wdk-proof/page.tsx
api/wdk/smoke/route.ts
components/
ai/
landing/
treasury/
ui/
wallet/
data/
demoTreasury.ts
lib/
qvac/qvacTreasuryAssistant.ts
treasury/treasuryRules.ts
treasury/treasuryStorage.ts
wdk/guarded/
wdk/wdkSmokeVerification.ts
wdk/wdkTreasuryAdapter.ts
types/
treasury.ts
scripts/
wdk-smoke-test.ts
wdk-policy-demo.ts
docs/
ARCHITECTURE.md
SECURITY_MODEL.md
WDK_API_RESEARCH.md
TRACK_COMPLIANCE.md
WDK_INTEGRATION_NOTES.md
Runtime dependencies:
- Next.js
- React
- Tailwind CSS
- lucide-react icons
@tetherto/wdk@tetherto/wdk-wallet-evm
Development dependencies:
- TypeScript
- ESLint
- Next.js ESLint config
tsx- Vitest
External services:
- Vercel hosts the live demo.
npm run wdk:smokeuses a public Sepolia RPC endpoint by default.- The browser app itself does not call blockchain APIs in the current MVP.
Cloud AI APIs:
- None
Pre-built UI kits:
- None. UI components are custom Tailwind/React components.
- Browser payment execution is a visualization only.
- No real token transaction is broadcast by default.
- MockUSDT is a test-token label, not official USDt; the Sepolia placeholder address used by the proof has no token bytecode and is marked
missing-contract. - The
/api/wdk/smokeendpoint returnsunsupported_runtimestatus (WDK native addons cannot bundle for Vercel serverless). - QVAC SDK inference is not implemented.
- No authentication.
- No backend database.
- Browser localStorage is used for demo persistence.
- The wallet address shown in the browser is a demo placeholder.
- The app is not production custody software.
No prior CupTreasury code was reused. The idea is inspired by practical experience with payment authorization flows, Web3 MVPs, and hackathon product design, but this implementation was built for this hackathon workspace.
Apache License 2.0. See LICENSE.