Skip to content

leopcortes/greentoken-cardano

Repository files navigation

Greentoken Cardano

Sistema de rastreamento de reciclagem de garrafas na blockchain Cardano usando smart contracts Plutus V2. Cada garrafa passa por 5 estágios (inserted -> compacted -> collected -> atstation -> shredded), e o reciclador recebe tokens Greentoken como recompensa a cada transição.


Arquitetura

Camada Tecnologia Descrição
On-chain Haskell / Plutus V2 Smart contract que valida transições de estágio
Off-chain Bash + cardano-cli Scripts para operar diretamente na blockchain
Backend Node.js + TypeScript + PostgreSQL API REST que integra blockchain e banco de dados
Frontend React + TypeScript + Vite + TailwindCSS Dashboard web para gerenciar o sistema

Fluxo de integração com a blockchain

  Dashboard Frontend
         |
         |--- API REST (Backend Node.js)
         |        |
         |        |-- Submete transação na blockchain Cardano (cardano-cli)
         |        |-- Registra garrafa + tx pendente no PostgreSQL
         |
         |   ~~~ confirmation worker (polling a cada 15s) ~~~
         |
         |        |-- Detecta UTxO confirmado on-chain
         |        |     |-- Atualiza tx -> confirmed
         |        |     |-- Atualiza garrafa -> utxo_hash
         |        |     |-- Registra recompensa Greentoken
         |
         |--- Dados disponíveis via API e renderizados no dashboard

Como cada operação usa a blockchain Cardano

Operação Transação on-chain Detalhes
Criar garrafa Mint de NFT + 10 Greentoken Cria um UTxO no endereço do script Plutus com datum {user, bottleId, stage=inserted}. Minta 10 Greentoken e envia à carteira do reciclador.
Compactar Advance stage (por garrafa) Consome o UTxO inserted do script, cria novo UTxO com datum stage=compacted. Minta 5 Greentoken para o reciclador. Requer redeemer de transição.
Coletar Advance stage (por garrafa) Consome UTxO compacted, cria UTxO collected. Minta 5 Greentoken.
Entregar na estação Advance stage (por garrafa) Consome UTxO collected, cria UTxO atstation. Minta 10 Greentoken.
Triturar Advance stage (por garrafa) Consome UTxO atstation, cria UTxO shredded. Minta 20 Greentoken.

Cada transação é submetida via cardano-cli, assinada pelo operador + policy key, e confirmada pelo confirmation worker que verifica a presença do UTxO no endereço do script a cada 15 segundos.


Recompensas por estágio

Estágio Greentoken Descrição
inserted 10 Garrafa inserida no container
compacted 5 Garrafas do container compactadas
collected 5 Container coletado pelo caminhão
atstation 10 Garrafas entregues na estação
shredded 20 Garrafas trituradas na estação
Total 50 Por garrafa, do início ao fim

Estrutura do Projeto

greentoken-cardano/
|-- onchain/src/Greentoken/
|   |-- BottleValidator.hs            # Smart contract Plutus V2
|-- offchain/test/Greentoken/
|   |-- BottleValidatorSpec.hs        # Testes do validador
|-- app/
|   |-- Main.hs                       # CLI para exportar o contrato
|   |-- WriteBottleValidator.hs       # Serialização do script
|-- assets/
|   |-- bottle-validator.plutus       # Contrato compilado
|   |-- policy/                       # Minting policy (policyID, script, chaves)
|   |-- redeemers/                    # Redeemers para cada transição de estágio
|   |-- wallet/                       # Endereço do operador e do script Plutus
|   |-- users/                        # Endereços e chaves dos usuários
|-- frontend/
|   |-- src/
|   |   |-- components/ui/            # Componentes shadcn (Radix + Tailwind)
|   |   |-- hooks/                    # Custom hooks (useSortable)
|   |   |-- lib/                      # Utilitários (truncateMiddle, labels)
|   |   |-- pages/                    # Páginas (Bottles, Users, Containers, Routes, Stations)
|   |   |-- services/api.ts           # Cliente HTTP tipado para a API REST
|   |   |-- App.tsx                   # Layout principal com abas
|   |   |-- index.css                 # Tema verde Tailwind + variáveis CSS
|   |-- vite.config.ts                # Vite + proxy /api -> backend:3000
|   |-- tailwind.config.js            # Tailwind v3 + tokens shadcn
|   |-- package.json
|-- backend/
|   |-- db/schema.sql                 # Schema PostgreSQL (DDL + seed)
|   |-- src/
|   |   |-- services/                 # Lógica de negócio (bottle, container, cardano)
|   |   |-- routes/                   # Endpoints Express
|   |   |-- db/queries/               # Queries PostgreSQL tipadas
|   |   |-- workers/                  # Confirmation worker (polling blockchain)
|   |-- .env.example                  # Template de variáveis de ambiente
|   |-- package.json
|   |-- tsconfig.json
|-- scripts/
|   |-- _db-helper.sh                 # Helper: integração scripts <-> PostgreSQL
|   |-- setup-wallet.sh               # Setup: chaves do operador + endereço do script
|   |-- setup-policy.sh               # Setup: minting policy + policyID
|   |-- split-utxos.sh                # Fragmenta UTXO do operador para operações batch
|   |-- query-balance.sh              # Consulta saldo de qualquer endereço
|   |-- get-pubkey-hash.sh            # Helper: gerar pubkey hash a partir do addr da wallet
|-- SETUP-LOCAL.md                    # Guia completo de configuração local
|-- plutus-greentoken.cabal           # Configuração Haskell
|-- cabal.project                     # Dependências Haskell

Scripts

Configuração inicial (executar uma vez)

Script Função Uso
setup-wallet.sh Gera chaves do operador e endereço do script scripts/setup-wallet.sh
setup-policy.sh Gera minting policy e policyID scripts/setup-policy.sh

Operação

Script Função Uso
split-utxos.sh Fragmenta o UTXO do operador em N UTXOs menores scripts/split-utxos.sh [N] (padrão: 10)
query-balance.sh Saldo de qualquer endereço scripts/query-balance.sh [ADDR|USER_ID]

API REST

O backend roda na porta 3000 e expõe os seguintes endpoints:

Método Rota Descrição
GET /health Health check
Usuários
GET /users Lista usuários (?role=recycler|owner)
GET /users/:id Detalhe de um usuário
POST /users Cria usuário
GET /users/:id/rewards Recompensas + total Greentoken
Garrafas
GET /bottles Lista garrafas (?user_id=, ?stage=, ?container_id=, ?route_id=, ?station_id=)
GET /bottles/next-number Próximo número disponível para garrafa
GET /bottles/:id Detalhe + histórico (txs + rewards)
POST /bottles Cria garrafa (blockchain + banco)
Containers
GET /containers Lista containers (?status=all|active|full|compacted|in_route, ?owner_id=)
POST /containers Cria container
POST /containers/:id/compact Compacta garrafas inserted (>= 90% cheio)
POST /containers/:id/collected Marca como coletado (esvaziado)
Caminhões
GET /trucks Lista caminhões
POST /trucks Cadastra caminhão (license_plate)
Rotas
GET /routes Lista rotas de coleta
POST /routes Cria rota (truck_id + container_ids + station_id)
GET /routes/:id Detalhe da rota com paradas
POST /routes/stops/:stopId/collect Coleta parada (compacted -> collected)
POST /routes/:id/deliver Entrega garrafas na estação (collected -> atstation)
Estações
GET /stations Lista estações de tratamento
POST /stations Cria estação
GET /stations/:id/bottles Lista garrafas na estação
POST /stations/:id/shred Tritura garrafas atstation (atstation -> shredded)

Banco de Dados

Schema com 8 tabelas (backend/db/schema.sql):

  • users - recicladores e donos de pontos de coleta
  • containers - pontos físicos de coleta (volume, status: active/full/compacted/in_route/maintenance)
  • trucks - frota de caminhões (status: available/on_route/maintenance)
  • routes / route_stops - rotas de coleta com paradas em containers
  • bottles - espelha os estágios do contrato Plutus (utxo_hash + utxo_index)
  • blockchain_txs - log de auditoria de todas as transações submetidas
  • rewards - registro de Greentoken creditados por estágio
  • stations - estações de tratamento de resíduos

Quick Start

Consulte o SETUP-LOCAL.md para o guia completo. Resumo rápido:

# 1. Configurar PostgreSQL
sudo -u postgres psql -c "CREATE DATABASE greentoken_db;"
psql -U postgres -d greentoken_db -f backend/db/schema.sql

# 2. Gerar chaves do operador (wallet owner)
export CARDANO_NODE_SOCKET_PATH=~/cardano/preprod/node.socket
export CARDANO_NODE_MAGIC=1
scripts/setup-wallet.sh
scripts/setup-policy.sh

# 3. Financiar wallet do operador com tADA (via faucet testnet Preprod)
cat assets/wallet/payment.addr
# Cole o endereço no faucet: https://docs.cardano.org/cardano-testnets/tools/faucet

# 3.1. Fragmentar UTXOs do operador (necessário para operações batch)
scripts/split-utxos.sh 100
# Aguarde ~20s e verifique: scripts/query-balance.sh

# 4. Iniciar nó e backend
cardano-start
cd backend && cp .env.example .env && npm install && npm run dev

# 5. Iniciar o frontend
cd frontend && npm install && npm run dev
# Acesse http://localhost:5173

# 6. Criar usuários no frontend:
#    - Owner: usar endereço de assets/wallet/payment.addr
#      scripts/get-pubkey-hash.sh $(cat assets/wallet/payment.addr)
#    - Recycler: criar wallet via Lace (extensão Chrome, rede Preprod)
#      scripts/get-pubkey-hash.sh <ENDERECO_LACE>
#    Recyclers NÃO precisam de tADA (transações financiadas pelo owner)

Frontend (Dashboard)

Dashboard web construído com React + TypeScript + Vite + TailwindCSS v3 + shadcn/ui (componentes Radix UI).

Funcionalidades

  • 5 abas: Usuários, Garrafas, Containers, Rotas/Caminhões, Estações de Tratamento
  • CRUD completo: criar e visualizar registros de cada entidade via interface gráfica
  • Bloqueios de fluxo: botões desabilitados conforme regras de negócio (ex: não compactar container < 90%, não entregar na estação sem coletar todas as paradas)
  • Cooldown de blockchain: após criar uma garrafa, o botão fica desabilitado até a transação ser confirmada on-chain (polling automático a cada 5s)
  • Rotas de coleta: selecionar caminhão + containers compactados + estação de destino, coletar paradas e entregar na estação
  • Recompensas: dialog para visualizar recompensas Greentoken de cada usuário
  • UX: botões de copiar, colunas ordenáveis, truncamento inteligente de endereços, tooltips explicativos, mensagens de erro formatadas

Execução

cd frontend
npm install
npm run dev    # http://localhost:5173

O Vite faz proxy de /api/* para http://localhost:3000 (backend). O backend precisa estar rodando.


Configuração de Wallets

Antes de usar o sistema, é necessário configurar as wallets Cardano para cada tipo de usuário:

Wallet do Owner (operador)

A wallet do owner é criada via script e é responsável por financiar todas as transações on-chain (mint de NFTs, transições de estágio, recompensas). Sem ela, nenhuma operação na blockchain funciona.

  1. Gere a wallet com scripts/setup-wallet.sh (cria chaves em assets/wallet/)
  2. Financie a wallet com tADA via faucet da testnet Preprod
  3. Com o endereço (payment.addr) e o pubkey hash (scripts/get-pubkey-hash.sh), crie o usuário owner no frontend

Wallet dos Recyclers (recicladores)

As wallets dos recicladores servem para identificar o usuário e receber recompensas Greentoken. As transações são financiadas pela wallet do owner, portanto recicladores não precisam de tADA.

  1. Recomendado: Crie a wallet pela extensão Lace Wallet no Chrome (rede Preprod)
  2. Alternativa: Crie via cardano-cli (ver SETUP-LOCAL.md)
  3. Com o endereço da wallet e o pubkey hash (scripts/get-pubkey-hash.sh <ENDERECO>), crie o usuário recycler no frontend

Consulte o SETUP-LOCAL.md para instruções detalhadas passo a passo.


Fluxo de Utilização

O sistema segue um fluxo sequencial com bloqueios para evitar que etapas sejam puladas:

1. Configurar Wallets (owner via script + recycler via Lace/script)
         |
2. Criar Usuários no frontend (owner e recycler, com wallet address + pubkey hash)
         |
3. Criar Container (associado a um proprietário)
         |
4. Inserir Garrafa -> associada a um container e um usuário
   |  (garrafa: inserted | recompensa: 10 Greentoken)
   |  [botão bloqueado até confirmação on-chain da garrafa anterior]
         |
5. Container >= 90% -> botão "Compactar" habilitado
   |  (garrafa: inserted -> compacted | recompensa: 5 Greentoken)
   |  [container muda para status "compactado" após compactação]
         |
6. Criar Rota de Coleta
   |  (selecionar caminhão disponível + containers compactados + estação de destino)
         |
7. Coletar Paradas da Rota (uma a uma)
   |  (garrafa: compacted -> collected | recompensa: 5 Greentoken)
   |  [garrafas saem do container e ficam associadas ao caminhão]
   |  [container volta a status "ativo" com volume zerado]
         |
8. Entregar na Estação (só após TODAS as paradas coletadas)
   |  (garrafa: collected -> atstation | recompensa: 10 Greentoken)
   |  [garrafas saem do caminhão e ficam associadas à estação]
         |
9. Triturar na Estação
   (garrafa: atstation -> shredded | recompensa: 20 Greentoken)

Total de recompensa por garrafa: 50 Greentoken


Próximos Passos

  • Frontend web para recicladores e owners
  • Implementar lógica de rotas de caminhão (CRUD de caminhões, criação de rotas, coleta de paradas)
  • Estações de tratamento e trituração
  • Bloqueios de fluxo no frontend (evitar etapas fora de ordem)
  • Cooldown de blockchain na criação de garrafas
  • Correção de recompensas em operações batch multi-usuário
  • Lidar com delays de operações na blockchain (validação de UTXOs confirmados + fragmentação de UTXOs)
  • Adicionar autenticação na API
  • Testes automatizados para o backend
  • Migrar de child_process para cardano-serialization-lib
  • Deploy em produção (mainnet)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors