ABCI Routes - Blockchain Abstraction
Documentação completa das rotas ABCI (Application Blockchain Interface) que fornecem abstração para integração com contratos inteligentes e múltiplas redes blockchain.
Visão Geral ABCI
O que são as Rotas ABCI?
As rotas ABCI são endpoints internos que abstraem interações com blockchain, permitindo que a API Ekonavi trabalhe com qualquer rede blockchain sem conhecer detalhes específicos de implementação.
┌─────────────────────────────────────────────────────────────────┐
│ ABCI Architecture │
├─────────────────────────────────────────────────────────────────┤
│ API Layer (api.ekonavi.com) │
│ ├── User Endpoints (/v1/*) │
│ ├── Admin Endpoints (/v1/admin/*) │
│ └── Public Endpoints (/v1/public/*) │
├─────────────────────────────────────────────────────────────────┤
│ ABCI Layer (Blockchain Abstraction) │
│ ├── /abci/contracts/* (Smart contract operations) │
│ ├── /abci/blockchains/* (Network management) │
│ └── /abci/tokens/* (Token operations) │
├─────────────────────────────────────────────────────────────────┤
│ Blockchain Implementation Layer │
│ ├── Ethereum Client │
│ ├── Polygon Client │
│ ├── Sepolia Client (Testing) │
│ └── Custom Network Clients │
└─────────────────────────────────────────────────────────────────┘
Benefícios da Abstração ABCI
- Multi-chain Support: Funciona com qualquer rede EVM
- Flexibilidade: Fácil adição de novas blockchains
- Manutenibilidade: Código agnóstico à blockchain
- Testing: Permite mock de interações blockchain
- Performance: Otimizações específicas por rede
Endpoints ABCI Contracts
POST /abci/contracts/mint-role-token
Minta tokens de função (Producer, Verifier, Valuator, Certifier) para carteiras de usuários.
Request
POST /abci/contracts/mint-role-token
Content-Type: application/json
Authorization: Bearer <admin-jwt-token>
{
"userAddress": "0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3",
"roleType": "producer",
"blockchainId": "eth-mainnet-001",
"metadata": {
"approvalId": "req_12345",
"approvedBy": "admin_67890",
"approvedAt": "2024-09-28T10:30:00Z"
}
}
Request Schema
interface MintRoleTokenRequest {
userAddress: string; // Ethereum address (42 chars, starts with 0x)
roleType: 'producer' | 'verifier' | 'valuator' | 'certifier';
blockchainId: string; // UUID of supported blockchain
metadata?: { // Optional metadata
approvalId?: string;
approvedBy?: string;
approvedAt?: string;
notes?: string;
};
}
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"transactionHash": "0x8b2f9c1a4d6e8f3b2a5c7e9f1d4b6a8c0e2f4d6b8a0c3e5f7d9b1a3c5e7f9b1a3",
"blockNumber": 18450123,
"gasUsed": "67432",
"gasPrice": "15000000000",
"tokenId": 10000,
"tokenType": "role",
"confirmations": 1,
"timestamp": "2024-09-28T10:30:45Z"
},
"metadata": {
"blockchain": {
"name": "Ethereum Mainnet",
"chainId": 1,
"network": "ethereum"
},
"contract": {
"address": "0x1234567890abcdef1234567890abcdef12345678",
"version": "1.0.0"
}
}
}
Código de Implementação
// Implementação do endpoint
app.post('/abci/contracts/mint-role-token', requireRole('admin'), async (c) => {
const { userAddress, roleType, blockchainId, metadata } = await c.req.json();
try {
// 1. Validate request
const validation = validateMintRoleTokenRequest({ userAddress, roleType, blockchainId });
if (!validation.success) {
return c.json({ error: 'Invalid request', details: validation.errors }, 400);
}
// 2. Get blockchain client
const blockchainClient = await blockchainService.getClient(blockchainId);
// 3. Mint role token
const tokenId = getRoleTokenId(roleType);
const transaction = await blockchainClient.mintRoleToken(
userAddress,
tokenId,
encodeMetadata(metadata)
);
// 4. Wait for confirmation
const receipt = await transaction.wait();
// 5. Update database
await db.tokenBalance.create({
data: {
walletId: await getWalletId(userAddress, blockchainId),
tokenId: tokenId,
balance: 1,
transactionHash: receipt.transactionHash,
blockNumber: receipt.blockNumber
}
});
// 6. Return response
return c.json({
success: true,
data: {
transactionHash: receipt.transactionHash,
blockNumber: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString(),
gasPrice: receipt.effectiveGasPrice.toString(),
tokenId: tokenId,
tokenType: 'role',
confirmations: receipt.confirmations,
timestamp: new Date().toISOString()
},
metadata: {
blockchain: await getBlockchainInfo(blockchainId),
contract: await getContractInfo(blockchainId)
}
});
} catch (error) {
console.error('Error minting role token:', error);
return c.json({
error: 'Failed to mint role token',
message: error.message
}, 500);
}
});
// Helper functions
const getRoleTokenId = (roleType: string): number => {
const roleTokenIds = {
producer: 10000,
verifier: 10100,
valuator: 10200,
certifier: 10300
};
return roleTokenIds[roleType];
};
POST /abci/contracts/mint-entity-token
Minta tokens de entidade (Reports, Verifications, Valuations, Certificates) para representar elementos do workflow ESG.
Request
POST /abci/contracts/mint-entity-token
Content-Type: application/json
Authorization: Bearer <user-jwt-token>
{
"userAddress": "0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3",
"entityType": "certificate",
"entityId": "cert_98765",
"blockchainId": "polygon-001",
"amount": 1,
"metadata": {
"name": "ESG Certificate #123",
"description": "Carbon sequestration certificate for sustainable farming",
"image": "https://ipfs.io/ipfs/QmX...abc",
"attributes": [
{
"trait_type": "Certificate Type",
"value": "Carbon Sequestration"
},
{
"trait_type": "Carbon Credits",
"value": 15.5
},
{
"trait_type": "Project Area",
"value": "50.2 hectares"
}
],
"external_url": "https://ekonavi.com/cert/certificates/cert_98765"
}
}
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"transactionHash": "0x9c3f8a2b5d7e9f1a3c5e7f9b1a3c5e7f9b1a3c5e7f9b1a3c5e7f9b1a3c5e7f9b",
"blockNumber": 48652087,
"gasUsed": "89234",
"tokenId": 1300,
"amount": 1,
"metadataUri": "https://ipfs.io/ipfs/QmY...def",
"confirmations": 1
},
"metadata": {
"entityType": "certificate",
"entityId": "cert_98765",
"ipfsHash": "QmY...def",
"blockchain": {
"name": "Polygon",
"chainId": 137
}
}
}
GET /abci/contracts/token-balance
Consulta saldo de tokens específicos na carteira do usuário.
Request
GET /abci/contracts/token-balance?userAddress=0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3&tokenId=10000&blockchainId=eth-mainnet-001
Authorization: Bearer <jwt-token>
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"userAddress": "0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3",
"tokenId": 10000,
"balance": "1",
"tokenType": "role",
"tokenName": "Producer Role Token",
"isSoulbound": true,
"mintedAt": "2024-09-15T14:20:30Z",
"lastUpdated": "2024-09-28T10:30:45Z"
},
"metadata": {
"blockchain": {
"name": "Ethereum Mainnet",
"chainId": 1
},
"contractAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
}
Endpoints ABCI Blockchains
GET /abci/blockchains/list
Lista todas as redes blockchain suportadas pela plataforma.
Request
GET /abci/blockchains/list
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": [
{
"id": "eth-mainnet-001",
"name": "Ethereum Mainnet",
"chainId": 1,
"network": "ethereum",
"rpcUrl": "https://mainnet.infura.io/v3/***",
"contractAddress": "0x1234567890abcdef1234567890abcdef12345678",
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"blockExplorer": "https://etherscan.io",
"status": "active",
"gasPrice": {
"low": "12000000000",
"standard": "15000000000",
"fast": "20000000000"
}
},
{
"id": "polygon-001",
"name": "Polygon",
"chainId": 137,
"network": "polygon",
"rpcUrl": "https://polygon-rpc.com",
"contractAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
"nativeCurrency": {
"name": "MATIC",
"symbol": "MATIC",
"decimals": 18
},
"blockExplorer": "https://polygonscan.com",
"status": "active",
"gasPrice": {
"low": "30000000000",
"standard": "35000000000",
"fast": "40000000000"
}
},
{
"id": "sepolia-001",
"name": "Ethereum Sepolia",
"chainId": 11155111,
"network": "sepolia",
"rpcUrl": "https://sepolia.infura.io/v3/***",
"contractAddress": "0x9876543210fedcba9876543210fedcba98765432",
"nativeCurrency": {
"name": "Sepolia Ether",
"symbol": "ETH",
"decimals": 18
},
"blockExplorer": "https://sepolia.etherscan.io",
"status": "testnet",
"gasPrice": {
"low": "1000000000",
"standard": "2000000000",
"fast": "3000000000"
}
}
],
"metadata": {
"totalNetworks": 3,
"activeNetworks": 2,
"testNetworks": 1
}
}
GET /abci/blockchains/{id}/status
Verifica o status de uma rede blockchain específica.
Request
GET /abci/blockchains/eth-mainnet-001/status
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"id": "eth-mainnet-001",
"name": "Ethereum Mainnet",
"status": "healthy",
"latestBlock": 18450123,
"blockTime": 12.1,
"gasPrice": {
"current": "15234567890",
"recommended": {
"low": "12000000000",
"standard": "15000000000",
"fast": "20000000000"
}
},
"contractStatus": {
"address": "0x1234567890abcdef1234567890abcdef12345678",
"deployed": true,
"version": "1.0.0",
"lastUpgrade": "2024-09-15T10:00:00Z"
},
"health": {
"rpcConnectivity": "healthy",
"contractAccessible": "healthy",
"lastChecked": "2024-09-28T10:30:00Z"
}
}
}
Endpoints ABCI Tokens
GET /abci/tokens/metadata/{tokenId}
Recupera metadados de um token específico.
Request
GET /abci/tokens/metadata/1300?blockchainId=polygon-001
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"tokenId": 1300,
"tokenType": "entity",
"category": "certificate",
"name": "ESG Certificate #123",
"description": "Carbon sequestration certificate for sustainable farming project",
"image": "https://ipfs.io/ipfs/QmX...abc",
"external_url": "https://ekonavi.com/cert/certificates/cert_98765",
"attributes": [
{
"trait_type": "Certificate Type",
"value": "Carbon Sequestration"
},
{
"trait_type": "Carbon Credits",
"value": 15.5,
"display_type": "number"
},
{
"trait_type": "Project Area",
"value": "50.2 hectares"
},
{
"trait_type": "Issue Date",
"value": "2024-09-28",
"display_type": "date"
},
{
"trait_type": "Methodology",
"value": "VCS VM0042"
},
{
"trait_type": "Blockchain",
"value": "Polygon"
}
],
"properties": {
"issuer": "0x1234567890abcdef1234567890abcdef12345678",
"beneficiary": "0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3",
"issuedAt": "2024-09-28T10:30:45Z",
"expiresAt": null,
"transferable": true,
"revocable": false
}
},
"metadata": {
"ipfsHash": "QmY...def",
"blockchain": {
"name": "Polygon",
"chainId": 137
},
"lastUpdated": "2024-09-28T10:30:45Z"
}
}
GET /abci/tokens/user-balance
Recupera todos os tokens de um usuário em uma blockchain específica.
Request
GET /abci/tokens/user-balance?userAddress=0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3&blockchainId=polygon-001
Authorization: Bearer <jwt-token>
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"data": {
"userAddress": "0x742d35Cc4Bf4C4532CE3F1F1e9E2A0B5A5D5F4F3",
"totalTokens": 8,
"balances": [
{
"tokenId": 10000,
"tokenType": "role",
"category": "producer",
"balance": "1",
"name": "Producer Role Token",
"isSoulbound": true,
"mintedAt": "2024-09-15T14:20:30Z"
},
{
"tokenId": 10100,
"tokenType": "role",
"category": "verifier",
"balance": "1",
"name": "Verifier Role Token",
"isSoulbound": true,
"mintedAt": "2024-09-20T09:15:22Z"
},
{
"tokenId": 1000,
"tokenType": "entity",
"category": "report",
"balance": "3",
"name": "ESG Report Token",
"isSoulbound": false,
"lastMinted": "2024-09-27T16:45:10Z"
},
{
"tokenId": 1100,
"tokenType": "entity",
"category": "verification",
"balance": "2",
"name": "Verification Token",
"isSoulbound": false,
"lastMinted": "2024-09-28T08:30:15Z"
},
{
"tokenId": 1300,
"tokenType": "entity",
"category": "certificate",
"balance": "1",
"name": "ESG Certificate Token",
"isSoulbound": false,
"lastMinted": "2024-09-28T10:30:45Z"
}
]
},
"metadata": {
"blockchain": {
"name": "Polygon",
"chainId": 137
},
"contractAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
"lastSynced": "2024-09-28T10:35:00Z"
}
}
Integração com Workflows
Fluxo de Aprovação de Papel
sequenceDiagram
participant A as Admin
participant API as API
participant ABCI as ABCI Layer
participant BC as Blockchain
A->>API: PUT /v1/admin/role-requests/{id}/approve
API->>API: Update role request status
API->>ABCI: POST /abci/contracts/mint-role-token
ABCI->>BC: Call mintRoleToken()
BC->>BC: Mint token to user wallet
BC->>ABCI: Return transaction receipt
ABCI->>API: Return transaction details
API->>API: Update user roles in database
API->>A: Return success response
Fluxo de Certificação ESG
sequenceDiagram
participant C as Certifier
participant API as API
participant ABCI as ABCI Layer
participant IPFS as IPFS
participant BC as Blockchain
C->>API: POST /v1/certifiers/certificates
API->>IPFS: Store certificate metadata
IPFS->>API: Return IPFS hash
API->>ABCI: POST /abci/contracts/mint-entity-token
ABCI->>BC: Call mintEntityToken()
BC->>BC: Mint certificate NFT
BC->>ABCI: Return transaction receipt
ABCI->>API: Return token details
API->>API: Update database with token info
API->>C: Return certificate with NFT details
Segurança e Autenticação
Autenticação ABCI
Middleware de Segurança
const abciAuthMiddleware = async (c: Context, next: Next) => {
const path = c.req.path;
// ABCI routes require elevated permissions
if (path.startsWith('/abci/')) {
const user = c.get('user');
if (!user) {
return c.json({ error: 'Authentication required for ABCI operations' }, 401);
}
// Check for admin role or system permissions
const roles = c.get('roles');
if (!roles.admin && !hasSystemPermission(user, path)) {
return c.json({ error: 'Insufficient permissions for ABCI operation' }, 403);
}
// Log ABCI operations for security audit
logABCIOperation(user.id, path, c.req.method);
}
await next();
};
Rate Limiting para ABCI
const abciRateLimiter = createRateLimiter({
windowMs: 60 * 1000, // 1 minute
max: 10, // 10 requests per minute for ABCI operations
keyGenerator: (c) => {
const user = c.get('user');
return `abci:${user?.id || c.req.header('CF-Connecting-IP')}`;
},
handler: (c) => {
return c.json({
error: 'Too many ABCI requests',
message: 'Rate limit exceeded for blockchain operations'
}, 429);
}
});
Validação de Transações
Pre-flight Checks
const validateMintingRequest = async (params: {
userAddress: string;
tokenType: string;
blockchainId: string;
}) => {
const checks = [
// Validate address format
isValidEthereumAddress(params.userAddress),
// Check if user exists and is associated with address
await isUserAssociatedWithAddress(params.userAddress),
// Validate blockchain is supported and active
await isBlockchainSupported(params.blockchainId),
// Check for duplicate token minting (role tokens)
await checkDuplicateRoleToken(params.userAddress, params.tokenType),
// Verify contract is deployed and accessible
await verifyContractStatus(params.blockchainId)
];
return checks.every(check => check === true);
};
Monitoramento e Observabilidade
Métricas ABCI
interface ABCIMetrics {
totalTransactions: number;
successfulMints: number;
failedMints: number;
averageGasUsed: number;
totalGasCost: string;
networkDistribution: {
ethereum: number;
polygon: number;
sepolia: number;
};
tokenDistribution: {
roleTokens: number;
entityTokens: number;
};
responseTimeMetrics: {
averageMs: number;
p95Ms: number;
p99Ms: number;
};
}
Health Checks
app.get('/abci/health', async (c) => {
const healthStatus = await Promise.all([
checkEthereumConnection(),
checkPolygonConnection(),
checkContractAccessibility(),
checkIPFSConnectivity()
]);
const allHealthy = healthStatus.every(status => status.healthy);
return c.json({
status: allHealthy ? 'healthy' : 'degraded',
checks: {
ethereum: healthStatus[0],
polygon: healthStatus[1],
contracts: healthStatus[2],
ipfs: healthStatus[3]
},
timestamp: new Date().toISOString()
}, allHealthy ? 200 : 503);
});
Testing ABCI Routes
Exemplo de Teste de Integração
describe('ABCI Contracts Integration', () => {
test('mint role token flow', async () => {
// Setup test user and blockchain
const testUser = await createTestUser();
const testBlockchain = 'sepolia-001';
// Request role token minting
const response = await request(app)
.post('/abci/contracts/mint-role-token')
.set('Authorization', `Bearer ${adminToken}`)
.send({
userAddress: testUser.walletAddress,
roleType: 'producer',
blockchainId: testBlockchain
});
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(response.body.data.tokenId).toBe(10000);
expect(response.body.data.transactionHash).toMatch(/^0x[a-fA-F0-9]{64}$/);
// Verify token balance on blockchain
const balance = await request(app)
.get(`/abci/contracts/token-balance`)
.query({
userAddress: testUser.walletAddress,
tokenId: 10000,
blockchainId: testBlockchain
})
.set('Authorization', `Bearer ${testUser.token}`);
expect(balance.body.data.balance).toBe('1');
});
});
Próximos Passos
Para Desenvolvedores
- Setup Local - Configure ambiente com blockchains de teste (Sepolia)
- Testes - Execute testes de integração ABCI
- Monitoramento - Configure alertas de transação
Para Administradores
- Deploy Contratos - Deploy em produção
- Configuração de Rede - Adicionar novas blockchains
- Auditoria - Revisar logs de transações ABCI
As rotas ABCI garantem flexibilidade e abstração para integração blockchain em todo o ecossistema Ekonavi.