Skip to main content

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

  1. Setup Local - Configure ambiente com blockchains de teste (Sepolia)
  2. Testes - Execute testes de integração ABCI
  3. Monitoramento - Configure alertas de transação

Para Administradores

  1. Deploy Contratos - Deploy em produção
  2. Configuração de Rede - Adicionar novas blockchains
  3. Auditoria - Revisar logs de transações ABCI

As rotas ABCI garantem flexibilidade e abstração para integração blockchain em todo o ecossistema Ekonavi.