PayStream is an Algorand-based payroll MVP for cross-border contractor payouts using USDCa. The app lets an employer deploy or attach to a PayStream vault, deposit USDCa, and execute payouts to contractor wallets with a simple operator dashboard.
This repository is a monorepo built with AlgoKit:
- Smart contract project in Python (
projects/contracts) - Frontend project in React + TypeScript (
projects/frontend)
- What This Repo Contains
- Current MVP Scope
- Architecture
- Prerequisites
- Quick Start (TestNet - Recommended)
- LocalNet Setup (Optional)
- Environment Variables
- Runbook: Typical Payment Flow
- Smart Contract API
- Development Commands
- Troubleshooting
- Security and Production Notes
- Contributing
.
|-- projects/
| |-- contracts/ # Algorand smart contract project (Python)
| | |-- smart_contracts/pay_stream/contract.py
| | |-- smart_contracts/pay_stream/deploy_config.py
| | `-- smart_contracts/artifacts/pay_stream/
| `-- frontend/ # React app (operator + contractor UI)
| |-- src/components/PayStreamDashboard.tsx
| |-- src/contracts/PayStream.ts
| `-- src/utils/network/getAlgoClientConfigs.ts
|-- .algokit.toml # Workspace-level AlgoKit config
`-- README.md
- Deploy PayStream app (vault) from the dashboard.
- Vault opt-in to a configured ASA (USDCa by default).
- Deposit ASA to vault using grouped tx (asset transfer + app call).
- Payout from vault to contractor addresses (admin-only action).
- Withdraw funds back to admin (contract method exists, not exposed in current UI).
- Track
adminandtotal_depositedin global state.
- Contractor directory and preferred currency selection.
- 30-second quote preview and FX conversion simulation.
- Scheduled payouts and due processing queue.
- Contractor cash-out modes (
hold,instant,standard) as UI/workflow simulation. - CSV/PDF activity export.
- State persistence in browser
localStorage(network-scoped key).
src/components/PayStreamDashboard.tsx- Main product UI for employer, contractor, and metrics tabs.
- Wallet connection, deploy/attach, deposit, payout, schedules, cash-out, and export.
src/contracts/PayStream.ts- Generated typed client from ARC-56 app spec.
src/utils/network/getAlgoClientConfigs.ts- Reads Algod/Indexer/KMD configs from Vite env vars.
smart_contracts/pay_stream/contract.pyopt_in_to_asset(asset)deposit(txn)payout(recipient, asset, amount)withdraw_admin(asset, amount)
smart_contracts/__main__.py- Build/export contract artifacts and generate clients.
smart_contracts/pay_stream/deploy_config.py- Deployment helper using AlgoKit utils.
Install these before running the project:
- Node.js
>=20.0 - npm
>=9.0 - pnpm (optional, needed for
algokit project run buildin this workspace) - Python
>=3.12 - Poetry
- AlgoKit CLI
>=2.0.0 - Docker (needed for LocalNet)
- Pera Wallet browser extension (recommended for current dashboard flow)
- Clone and enter repo
git clone https://github.com/ShreyashDabhade/PayStream.git
cd PayStream- Bootstrap workspace dependencies
algokit project bootstrap all- Configure frontend env file (
projects/frontend/.env)
Use this TestNet baseline:
VITE_ENVIRONMENT=local
VITE_ALGOD_TOKEN=
VITE_ALGOD_SERVER=https://testnet-api.algonode.cloud
VITE_ALGOD_PORT=
VITE_ALGOD_NETWORK=testnet
VITE_INDEXER_TOKEN=
VITE_INDEXER_SERVER=https://testnet-idx.algonode.cloud
VITE_INDEXER_PORT=
VITE_USDCA_ASSET_ID=10458941- Start frontend
cd projects/frontend
npm run dev-
Open app in browser and connect wallet.
-
In
Employertab:
- Set asset ID (USDCa)
- Click
Deployto create a new vault, or set existing App ID and clickAttach - Deposit USDCa
- Add contractors and execute payouts
- Start LocalNet
algokit localnet start-
Configure
projects/frontend/.envusing local values fromprojects/frontend/.env.template. -
Set local asset id (if using AlgoKit default LocalNet assets):
VITE_USDCA_ASSET_ID=1023- Start frontend
cd projects/frontend
npm run devKnown limitation:
- Current dashboard connect flow explicitly prefers Pera wallet in
projects/frontend/src/components/PayStreamDashboard.tsx. - LocalNet KMD config exists in the app bootstrap layer, but the current connect button flow is optimized for TestNet/Pera.
Frontend config is read in projects/frontend/src/utils/network/getAlgoClientConfigs.ts.
| Variable | Required | Description |
|---|---|---|
VITE_ALGOD_SERVER |
Yes | Algod endpoint URL |
VITE_ALGOD_PORT |
Yes (can be empty string) | Algod port |
VITE_ALGOD_TOKEN |
Yes (can be empty string) | Algod API token |
VITE_ALGOD_NETWORK |
Yes | localnet, testnet, or mainnet |
VITE_INDEXER_SERVER |
Yes | Indexer endpoint URL |
VITE_INDEXER_PORT |
Yes (can be empty string) | Indexer port |
VITE_INDEXER_TOKEN |
Yes (can be empty string) | Indexer token |
VITE_USDCA_ASSET_ID |
Strongly recommended | ASA used for vault accounting and payouts |
VITE_KMD_SERVER |
LocalNet only | KMD endpoint |
VITE_KMD_PORT |
LocalNet only | KMD port |
VITE_KMD_TOKEN |
LocalNet only | KMD token |
VITE_KMD_WALLET |
LocalNet only | KMD wallet name |
VITE_KMD_PASSWORD |
LocalNet only | KMD wallet password |
Notes:
VITE_ALGOD_NODE_CONFIG_SERVER|PORT|TOKENare supported fallback names for Algod config.- Restart
npm run devafter changing env vars.
- Connect employer wallet.
- Deploy vault (or attach existing App ID).
- Deposit USDCa into vault.
- Add contractor and set preferred currency.
- Ensure contractor wallet is opted-in to configured asset.
- Generate quote (30s window) and execute payout.
- Optionally create schedules and process due items.
- Contractor tab can simulate cash-out modes and export history.
Contract source: projects/contracts/smart_contracts/pay_stream/contract.py
| Method | Purpose | Access Control |
|---|---|---|
opt_in_to_asset(asset) |
Opts vault into an asset so it can hold ASA balance | Admin only |
deposit(txn) |
Validates deposit transfer to app address and updates total | Caller supplies grouped transfer |
payout(recipient, asset, amount) |
Sends payout from vault to contractor via inner tx | Admin only |
withdraw_admin(asset, amount) |
Withdraws from vault to admin wallet | Admin only |
algokit project bootstrap all
algokit project run buildnpm run dev
npm run build
npm run lint
npm run test
npm run playwright:test
npm run generate:app-clientsalgokit project run build
algokit project run lint
algokit project run test
algokit project deploy localnet
algokit project deploy testnetIf contract ABI changes, regenerate/link frontend clients:
cd projects/contracts
algokit project run build
cd ../frontend
npm run generate:app-clients- Cause: missing
VITE_ALGOD_SERVER(or fallback env vars). - Fix: update
projects/frontend/.envand restart dev server.
- Use
Reset Wallet Sessionbutton in UI. - Reconnect wallet and retry transaction.
- Contractor must opt-in to the configured ASA before payout.
- Ensure connected wallet matches contractor address when running opt-in action.
- Deposit intentionally creates a grouped operation (asset transfer + app call).
- In Pera this appears as one "Multiple Transaction Request".
- Verify Indexer env values.
- Ensure App ID is valid and network matches your deployed app.
- Browser likely blocked pop-ups.
- Allow pop-ups for localhost and retry.
- This is an MVP and has not been audited.
withdraw_adminallows admin withdrawal by design.- Quote, FX conversion, scheduling, and cash-out flows are currently client-side logic.
- Browser
localStorageis not secure storage for sensitive business records. - For production, add:
- secure backend for quote and settlement orchestration,
- custody and role controls (for example multisig/admin policies),
- monitoring/alerting and compliance workflows,
- independent smart contract and application security review.
- Manager Role: Add a second authorized address to the smart contract to delegate payout tasks without granting full withdrawal rights.
- Asset Registry: Update the frontend to store and manage multiple stablecoin asset IDs (e.g., USDT, EURS) rather than a single hardcoded ID.
- Balance Alerts: Implement a UI notification that calculates if the current vault balance is enough to cover all "Active" scheduled payouts for the upcoming month.
- Contractor Self-Onboarding: Create a dedicated view for contractors to connect their own wallets and execute the required asset opt-in transaction independently.
- Transaction Metadata: Utilize the Algorand "note" field in the deposit method to attach business labels like "Project Alpha Bonus" to on-chain records.
- Batch Processing: Enable the employer to group multiple pending payouts into a single atomic transaction for better efficiency.
- Payout Caps: Define a maximum allowable amount per payout in the contract's global state to prevent accidental or unauthorized large transfers.
- Secure History: Move from localStorage to a lightweight backend or decentralized storage to prevent the loss of activity logs when a browser cache is cleared.
- Create a feature branch.
- Keep changes scoped and documented.
- Run lint/build before opening a PR.
- Include screenshots or reproduction steps for UI or flow changes.