Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 376 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,378 @@
# Token Streaming
# Stacks Token Streaming - Stream Transfer Feature

A token streaming DeFi protocol built using Clarity for Stacks. Inspired by Superfluid.
A decentralized application for streaming STX token payments with the ability to transfer stream ownership between addresses.

This project was done as part of the "Introduction to Stacks" course for the "Stacks Developer Degree" on LearnWeb3.
## Overview

This project implements a token streaming protocol on the Stacks blockchain, allowing users to create payment streams that release tokens over time. The **Stream Transfer** feature enables recipients to transfer their stream ownership to another address, useful for wallet migrations, gifting, or trading stream rights.

## Features

### Core Streaming Functionality
- Create payment streams with configurable timeframes
- Withdraw tokens proportional to elapsed time
- Refuel streams with additional tokens
- Reclaim excess tokens after stream completion
- Update stream parameters with dual-party consent

### Stream Transfer Feature (NEW)
- Transfer stream ownership to another recipient
- Security validations prevent invalid transfers
- Maintains stream balance and payment schedule
- Multiple sequential transfers supported
- Complete audit trail on-chain

## Tech Stack

- **Smart Contracts:** Clarity (Stacks blockchain)
- **Testing:** Clarinet SDK with Vitest
- **Frontend:** React 18 with TypeScript
- **Blockchain Integration:** Stacks.js libraries
- **Styling:** Tailwind CSS
- **Build Tool:** Vite

## Project Structure

```
stacks-token-streaming/
├── contracts/
│ └── stream.clar # Smart contract with transfer-stream function
├── tests/
│ └── stream.test.ts # 17 comprehensive tests
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ └── StreamTransfer.tsx # Main transfer component
│ │ ├── App.tsx # Application wrapper
│ │ ├── App.css # Component styles
│ │ ├── main.tsx # React entry point
│ │ └── index.css # Global styles
│ ├── index.html # HTML entry
│ ├── package.json # Dependencies
│ ├── tsconfig.json # TypeScript config
│ ├── vite.config.ts # Vite configuration
│ └── tailwind.config.js # Tailwind configuration
└── Clarinet.toml # Clarinet project config
```

## Installation

### Prerequisites

- Node.js v18 or higher
- npm or yarn
- Clarinet CLI
- Stacks wallet (Hiro Wallet or Leather Wallet)

### Setup Instructions

1. **Clone the repository**
```bash
git clone <repository-url>
cd stacks-token-streaming
```

2. **Install contract dependencies**
```bash
clarinet check
```

3. **Run contract tests**
```bash
npm test
```

4. **Set up frontend**
```bash
cd frontend
npm install
```

5. **Start development server**
```bash
npm run dev
```
Application will be available at `http://localhost:3000`

## Smart Contract

### transfer-stream Function

```clarity
(define-public (transfer-stream
(stream-id uint)
(new-recipient principal)
)
...
)
```

**Parameters:**
- `stream-id`: The ID of the stream to transfer
- `new-recipient`: The principal address of the new recipient

**Security Validations:**
- Only current recipient can initiate transfer
- Cannot transfer to yourself
- Cannot transfer to the original sender
- Stream must exist

**Returns:** `(ok true)` on success, error code on failure

### Error Codes

| Code | Constant | Description |
|------|----------|-------------|
| u0 | ERR_UNAUTHORIZED | Caller is not authorized |
| u1 | ERR_INVALID_SIGNATURE | Invalid signature provided |
| u2 | ERR_STREAM_STILL_ACTIVE | Stream is still active |
| u3 | ERR_INVALID_STREAM_ID | Stream does not exist |
| u4 | ERR_INVALID_AMOUNT | Amount is zero or negative |
| u5 | ERR_INVALID_TIMEFRAME | Invalid timeframe parameters |
| u6 | ERR_CANNOT_TRANSFER_TO_SELF | Cannot transfer to same address |
| u7 | ERR_CANNOT_TRANSFER_TO_SENDER | Cannot transfer to sender |

## Testing

### Run All Tests

```bash
npm test
```

### Test Coverage

**Total Tests:** 17 (100% passing)

**Test Categories:**
- Stream initialization and creation
- Refueling functionality
- Withdrawal mechanisms
- Authorization checks
- Signature verification
- Parameter updates
- **Stream transfer feature (9 new tests)**

**Stream Transfer Tests:**
1. Successful transfer to new recipient
2. Authorization validation (only recipient can transfer)
3. Self-transfer prevention
4. Sender-transfer prevention
5. Invalid stream ID handling
6. New recipient can withdraw after transfer
7. Old recipient loses access after transfer
8. Multiple sequential transfers
9. Stream properties remain unchanged

### Example Test

```typescript
it("ensures recipient can successfully transfer stream to new recipient", () => {
const transferResult = simnet.callPublicFn(
"stream",
"transfer-stream",
[Cl.uint(0), Cl.principal(newRecipient)],
recipient
);

expect(transferResult.result).toBeOk(Cl.bool(true));
// Verify stream ownership updated...
});
```

## Frontend Usage

### Connecting Wallet

1. Click "Connect Wallet" button
2. Approve connection in your Stacks wallet
3. Your address will be displayed

### Transferring a Stream

1. Enter the Stream ID you want to transfer
2. Click "Fetch" to load stream information
3. Enter the new recipient's Stacks address (must start with ST or SP)
4. Click "Transfer Stream"
5. Approve the transaction in your wallet
6. Wait for confirmation
7. View transaction on Stacks Explorer

### Address Validation

The frontend validates addresses in real-time:
- Must start with `ST` (testnet) or `SP` (mainnet)
- Cannot be your own address
- Cannot be the stream sender's address

## API Reference

### Frontend Component Props

```typescript
interface StreamTransferProps {
contractAddress: string; // Deployed contract address
contractName: string; // Contract name (default: "stream")
network?: 'testnet' | 'mainnet'; // Network selection
}
```

### Contract Functions (Read-Only)

```clarity
(balance-of (stream-id uint) (who principal))
(calculate-block-delta (timeframe (tuple ...)))
(hash-stream (stream-id uint) ...)
(validate-signature (hash (buff 32)) ...)
```

### Contract Functions (Public)

```clarity
(stream-to (recipient principal) (initial-balance uint) ...)
(refuel (stream-id uint) (amount uint))
(withdraw (stream-id uint))
(refund (stream-id uint))
(update-details (stream-id uint) ...)
(transfer-stream (stream-id uint) (new-recipient principal))
```

## Deployment

### Deploy to Testnet

```bash
clarinet deployments generate --testnet
clarinet deployments apply --testnet
```

### Deploy to Mainnet

```bash
clarinet deployments generate --mainnet
clarinet deployments apply --mainnet
```

### Update Frontend Contract Address

After deployment, update the contract address in `frontend/src/App.tsx`:

```typescript
<StreamTransfer
contractAddress="YOUR_DEPLOYED_CONTRACT_ADDRESS"
contractName="stream"
network="testnet"
/>
```

## Development

### Running Tests in Watch Mode

```bash
npm test -- --watch
```

### Building for Production

```bash
cd frontend
npm run build
```

### Linting and Formatting

```bash
# Check contract syntax
clarinet check

# TypeScript type checking
cd frontend
npx tsc --noEmit
```

## Security Considerations

1. **Authorization:** Only the current recipient can transfer streams
2. **Validation:** Multiple checks prevent invalid transfers
3. **State Integrity:** Stream balance and timeframe remain unchanged
4. **Audit Trail:** All transfers recorded on-chain
5. **Post Conditions:** Frontend uses post conditions to prevent unauthorized token transfers

## Known Limitations

1. Frontend uses simulated data for stream fetching (API integration pending)
2. No transfer fee mechanism (could be added as future enhancement)
3. No notification system for transfer events
4. Single stream transfer only (no batch transfers)

## Future Enhancements

- [ ] Add transfer history tracking
- [ ] Implement transfer fees
- [ ] Create transfer approval workflow (2-step transfer)
- [ ] Add batch transfer functionality
- [ ] Email/SMS notifications for transfers
- [ ] Stream marketplace for trading
- [ ] Mobile app support
- [ ] Multi-token support (beyond STX)

## Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

### Contribution Guidelines

- Write tests for all new features
- Follow existing code style
- Update documentation
- Ensure all tests pass before submitting PR

## Testing Checklist for Contributors

- [ ] Contract compiles without errors (`clarinet check`)
- [ ] All tests pass (`npm test`)
- [ ] Frontend builds successfully (`npm run build`)
- [ ] No TypeScript errors
- [ ] Code follows project style guidelines

## License

This project is part of the LearnWeb3 educational program.

## Resources

- [Stacks Documentation](https://docs.stacks.co/)
- [Clarity Language Reference](https://docs.stacks.co/clarity/)
- [Stacks.js Documentation](https://docs.stacks.co/stacks.js/)
- [Clarinet Documentation](https://docs.hiro.so/clarinet/)
- [LearnWeb3 DAO](https://learnweb3.io/)

## Support

For issues, questions, or suggestions:
- Open an issue on GitHub
- Contact the development team
- Join the Stacks Discord community

## Acknowledgments

- Built as part of LearnWeb3 Stacks curriculum
- Inspired by Sablier Protocol on Ethereum
- Uses Hiro's Clarinet development tools

## Author

**Your Name**
GitHub: @yourusername
Twitter: @yourhandle

---

**Project Status:** Active Development
**Version:** 1.0.0
**Last Updated:** October 2025
Loading