Full-stack blockchain solution for wine traceability from vineyard to consumer.
Supply Chain Tracker is a production-ready platform for tracking goods across every stage of a supply chain. Built with Solidity smart contracts, The Graph indexing, and a Next.js dashboard with complete internationalization (English/Spanish).
Smart Contract: 0xc9f05d6d9752c858c59e31c7d96799261d8841fe
Frontend: https://wineproof.vercel.app/
Features:
- β Role-based access control (Admin, Producer, Distributor, Retailer)
- β ERC-1155 batch tokenization
- β Transfer approval workflow
- β Complete transaction history with hashes
- β Real-time subgraph indexing
- β Bilingual UI (EN/ES)
| Path | Description |
|---|---|
web/ |
Next.js 16 application that provides the role-based dashboard, landing page, and wallet integrations. |
sc/ |
Foundry project with the smart contracts that mint ERC-1155 tokens for each batch and enforce transfer permissions. |
subgraph/ |
The Graph manifest that indexes on-chain activity for analytics and timeline views. |
scripts/ |
Helper scripts for seeding local networks and syncing environments. |
- Node.js 18+ (for Next.js 14 web app)
- npm 9+ or compatible package manager
- Foundry for smart contract development
- Docker (optional, for local Graph node)
- Metamask or compatible Web3 wallet
Create environment files for each component:
# Web application
cp web/.env.example web/.env.local
# Smart contracts
cp sc/.env.example sc/.env.localImportant: Never commit .env.local files. See SECURITY_KEYS.md for best practices.
cd web
npm install
npm run devVisit http://localhost:3000
Key Features:
- Bilingual UI (English/Spanish) via
src/i18n/dictionary.ts - Role-based dashboards (Admin, Producer, Distributor, Retailer)
- Real-time transaction hash display
- Token creation and transfer management
cd sc
forge install # first time only
forge build
forge testRun local blockchain:
anvilIn another terminal:
cd sc
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcast
forge script script/Seed.s.sol --rpc-url http://localhost:8545 --broadcastcd subgraph
npm install
npm run codegen
npm run build
npm run deploy-local # requires local graph-nodeFor detailed local setup, see subgraph/README.md.
# One-time setup: create encrypted keystore
./scripts/setup_keystore.sh
# Deploy using keystore (prompts for password)
./scripts/deploy_sepolia_keystore.sh# Prompts for private key (hidden input)
./scripts/deploy_sepolia.shcd sc
forge script script/Deploy.s.sol \
--rpc-url $SEPOLIA_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify \
--etherscan-api-key $ETHERSCAN_API_KEYFor complete testnet guide, see DEPLOYMENT_TESTNET.md.
cd subgraph
# 1. Update contract address and start block
nano subgraph.sepolia.yaml
# 2. Copy to main config
cp subgraph.sepolia.yaml subgraph.yaml
# 3. Generate types
npm run codegen
# 4. Build
npm run build
# 5. Authenticate (get key from thegraph.com/studio)
graph auth --studio <YOUR_DEPLOY_KEY>
# 6. Deploy
graph deploy --studio supply-chain-trackerFor complete subgraph guide, see subgraph/DEPLOY_GUIDE.md.
cd web
# Run unit tests (Vitest)
npm run test
# Run linting (ESLint)
npm run lint
# Type checking
npm run type-checkcd sc
# Run all tests
forge test
# Run with verbosity
forge test -vvv
# Run specific test file
forge test --match-path test/SupplyChain.t.sol
# Gas report
forge test --gas-reportAll UI text is fully localized in English and Spanish.
Dictionary location: web/src/i18n/dictionary.ts
When adding new UI copy:
- Add the key to both
enandesobjects indictionary.ts - Use the
useI18n()hook in your component:
import { useI18n } from '@/contexts/I18nContext'
export default function MyComponent() {
const { t } = useI18n()
return <h1>{t('myNewKey')}</h1>
}- Update nested keys using dot notation:
// In dictionary.ts
export const dictionary = {
en: {
profile: {
title: 'My Profile',
edit: 'Edit Profile'
}
},
es: {
profile: {
title: 'Mi Perfil',
edit: 'Editar Perfil'
}
}
}
// In component
t('profile.title') // "My Profile" or "Mi Perfil"Important: Always keep both languages in sync!
β NEVER DO THIS:
# .env file committed to git
PRIVATE_KEY=0x1234567890abcdef...β RECOMMENDED OPTIONS:
-
Encrypted Keystore (Most Secure):
./scripts/setup_keystore.sh
Creates AES-256 encrypted wallet in
~/.foundry/keystores/ -
Secure Input (No File Storage):
./scripts/deploy_sepolia.sh
Prompts for key with hidden input, clears after use
-
Environment Variable (Development Only):
- Use
.env.local(already in.gitignore) - Never commit to repository
- Clear after session
- Use
See SECURITY_KEYS.md for:
- Attack vectors and prevention
- Keystore management
- Hardware wallet integration
- Production deployment checklist
| Document | Description |
|---|---|
| SECURITY_KEYS.md | Complete guide for secure key management |
| DEPLOYMENT_TESTNET.md | Step-by-step Sepolia deployment guide |
| subgraph/DEPLOY_GUIDE.md | The Graph Studio deployment walkthrough |
| THEGRAPH_GUIDE.md | Subgraph development and querying |
| web/README.md | Frontend architecture and components |
| sc/README.md | Smart contract documentation |
| Script | Purpose |
|---|---|
scripts/setup_keystore.sh |
Create encrypted Foundry keystore |
scripts/deploy_sepolia.sh |
Deploy to Sepolia with secure input |
scripts/deploy_sepolia_keystore.sh |
Auto-generated keystore deployment |
scripts/deploy_local.sh |
Deploy to local Anvil chain |
subgraph/deploy.sh |
Deploy subgraph to local graph-node |
subgraph/setup.sh |
Start local graph-node with Docker |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Web Application β
β (Next.js 14 + TypeScript) β
β - Role-based dashboards β
β - i18n (EN/ES) β
β - Transaction hash tracking β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
β Web3 Provider (Ethers.js)
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β Smart Contracts β
β (Solidity + Foundry) β
β - ERC-1155 batch tokens β
β - Role-based access control β
β - Transfer approval workflow β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
β Events
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β The Graph Subgraph β
β (GraphQL Indexing) β
β - Token creation events β
β - Transfer history β
β - User role changes β
β - Transaction hashes β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Check Metamask is installed and unlocked
- Verify you're on the correct network (Sepolia for testnet)
- Check
NEXT_PUBLIC_CONTRACT_ADDRESSinweb/.env.local
- Ensure you have Sepolia ETH (get from faucet)
- Verify
SEPOLIA_RPC_URLis valid (Alchemy/Infura) - Check
ETHERSCAN_API_KEYfor verification
- Verify contract address in
subgraph.yamlmatches deployed contract - Check
startBlockis not before contract deployment - Ensure The Graph Studio shows "Synced" status
- Confirm subgraph is fully synced
- Check
NEXT_PUBLIC_SUBGRAPH_URLinweb/.env.local - Transaction hashes display immediately after creation (cached locally)
MIT License - see LICENSE file for details
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Note: All new UI strings must include both English and Spanish translations.
- Documentation: See guides in
/docsand component READMEs - Issues: Open a GitHub issue
- Security: See SECURITY.md for responsible disclosure
Made with β€οΈ for transparent supply chains