Decentralized crowdfunding dApp built by Cardano2VN on Cardano.
Decentralized crowdfunding application running on Cardano. Users can create campaigns, contribute ADA, withdraw funds when a campaign reaches its goal, or reclaim their contributions when a campaign expires without reaching its goal.
This project is built for the Cardano Preprod/Preview testnet, with smart contracts written in Aiken and transaction builders written with MeshJS.
- Connect a Cardano wallet in the browser.
- Create campaigns with a beneficiary, ADA goal, and deadline.
- Make multiple contributions to a campaign.
- Allow the beneficiary to withdraw the full campaign balance when the goal is reached and the deadline has passed.
- Allow contributors to reclaim their contributions after the deadline if the campaign does not reach its goal.
- Read campaigns directly from script address UTxOs through Blockfrost.
- Validate datum integrity, contributions, deadlines, and the beneficiary's signature on-chain.
- Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS
- Cardano integration: MeshJS 1.9
- Smart contract: Aiken, Plutus V3
- Chain provider: Blockfrost
- Tests: Jest and Aiken check
crowdfund/
├── frontend/ # Next.js dApp and server actions
│ └── src/
│ ├── actions/ # Transaction creation and submission workflows
│ ├── components/ # Wallet, campaign, donate, withdraw, and reclaim UI
│ ├── hooks/ # Wallet state
│ ├── providers/ # Blockfrost provider
│ ├── txbuilders/ # MeshJS transaction builders
│ └── libs/plutus.json # Compiled validator script
├── offchain/ # MeshJS utilities and standalone tests
│ └── src/
└── onchain/ # Aiken validator and on-chain tests
├── validators/crowdfund.ak
├── lib/types.ak
└── validators/tests/
- Node.js 20 or later and npm.
- Aiken v1.1.22 or later to build and check the contract.
- A Cardano wallet extension, such as Eternl or Nami.
- A Blockfrost API key for the selected network.
- Testnet ADA from a faucet when running on Preprod/Preview.
Create a .env.local file inside frontend/:
BLOCKFROST_API_KEY=your_blockfrost_api_key
APP_NETWORK=preview
APP_MNEMONIC=your_test_wallet_mnemonic
APP_WALLET_ADDRESS=your_test_wallet_address
KOIOS_TOKEN=APP_NETWORK defaults to preview. You can use mainnet after configuring the correct contract, API key, and production wallet. Never commit .env.local or a mnemonic to the repository.
APP_MNEMONIC is currently used by a server action to read campaign UTxOs from the script address. Use only a dedicated testnet wallet mnemonic for development.
cd frontend
npm install
npm run devOpen http://localhost:3000, connect a wallet on the correct network, then create a campaign or select an existing one.
Common commands:
npm run lint
npm run build
npm run startcd onchain
aiken check
aiken buildaiken check runs the tests in onchain/validators/tests. After building, the Plutus artifact is generated in onchain/plutus.json. If the frontend uses a new artifact, update the corresponding file at frontend/src/libs/plutus.json.
cd offchain
npm install
npm testThe frontend also contains MeshJS tests in frontend/src/tests. They can be run with Jest after extending the frontend test configuration if needed.
- Create: The wallet creates a UTxO at the script address with a datum containing the beneficiary, goal, deadline, and initial contributions.
- Donate: A contributor adds ADA and updates the contributions in the continuing output.
- Withdraw: The beneficiary signs a transaction to spend the script UTxO after the goal is reached and the deadline has passed.
- Reclaim: A contributor signs a transaction after the deadline to receive their contribution back if the goal was not reached. Other contributors can reclaim later.
- This is a Cardano testnet project. Do not use real funds until the smart contract and transaction builder have been fully audited.
- Deadlines are handled as POSIX timestamps in milliseconds by the application.
- A valid collateral UTxO is required in the wallet to submit Plutus transactions.
- Addresses, network, compiled script, and API key must all belong to the same Cardano environment.
- Blockfrost has request limits. If the campaign list does not update immediately, wait for the transaction to be confirmed and refresh the page.
- Fork the repository and create a branch for your changes.
- Run
aiken check,npm run lint, and the relevant tests. - Open a pull request describing the changes and the network used for testing.
No license has been defined for this repository yet. Add a LICENSE file before public release or accepting external contributions.