Supported Blockchains
This document provides detailed information about the blockchain networks supported by the Rahat Anticipatory Action platform, including Stellar Soroban, EVM-compatible networks, and their integration patterns.
Overview
The platform supports dual blockchain architecture, allowing deployment on both Stellar Soroban and EVM-compatible networks. This provides flexibility in choosing the most suitable blockchain for specific use cases and regional requirements.
Architecture
Core Components
1. Chain Service Interface
- Purpose: Abstract blockchain operations
- Location:
apps/aa/src/chain/interfaces/chain-service.interface.ts
- Features: Unified interface for different blockchain implementations
2. Stellar Integration
- Purpose: Primary blockchain for token operations
- Features: Soroban smart contracts, native asset management
- SDK: Stellar SDK with Soroban support
3. EVM Integration
- Purpose: Alternative blockchain deployment options
- Features: Solidity smart contracts, DeFi integration
- SDK: Ethers.js for EVM-compatible networks
1. Stellar Network
Overview
Stellar is the primary blockchain for the platform, offering fast transactions, low costs, and native asset support. The platform leverages Stellar's Soroban smart contract platform for advanced functionality.
Key Features
Transaction Characteristics
- Finality: 3-5 seconds
- Transaction Cost: ~0.00001 XLM per operation
- Throughput: 1,000+ transactions per second
- Consensus: Stellar Consensus Protocol (SCP)
Asset Management
// Stellar asset configuration
interface StellarAsset {
code: 'RAHAT';
issuer: string; // Stellar account that issues the asset
network: 'TESTNET' | 'PUBLIC';
decimals: 7;
}
Smart Contracts (Soroban)
Contract Structure
// soroban/trigger/contracts/trigger-manager/src/lib.rs
#[contract]
pub struct TriggerManager;
#[contractimpl]
impl TriggerManager {
pub fn initialize(env: Env, admin: Address) -> Result<(), Error> {
// Initialize contract with admin
Ok(())
}
pub fn create_trigger(
env: Env,
trigger_id: String,
conditions: Vec<String>,
actions: Vec<String>
) -> Result<(), Error> {
// Create new trigger with conditions and actions
Ok(())
}
pub fn execute_trigger(env: Env, trigger_id: String) -> Result<(), Error> {
// Execute trigger when conditions are met
Ok(())
}
}
Contract Deployment
# Build Soroban contract
cd soroban/trigger
stellar contract build
# Deploy to Stellar network
stellar contract deploy --network testnet target/wasm32-unknown-unknown/release/trigger_manager.wasm
Stellar Service Integration
Service Structure
// apps/aa/src/stellar/stellar.service.ts
@Injectable()
export class StellarService {
constructor(
private readonly receiveService: ReceiveService,
private readonly transactionService: TransactionService,
private readonly disbursementServices: DisbursementServices
) {}
async transferTokens(data: TransferTokensDto): Promise<any> {
return this.transactionService.transferTokens(
data.fromAddress,
data.toAddress,
data.amount,
data.assetCode
);
}
async fundAccount(data: FundAccountDto): Promise<any> {
return this.receiveService.fundAccount(
data.address,
data.amount,
data.assetCode
);
}
async disburse(data: DisburseDto): Promise<any> {
return this.disbursementServices.disburse(data);
}
}
Token Operations
// Token transfer operations
async transferTokensToBeneficiary(
fromAddress: string,
toAddress: string,
amount: number
): Promise<TransactionResult> {
const result = await this.stellarService.transferTokens({
fromAddress,
toAddress,
amount,
assetCode: 'RAHAT',
assetIssuer: process.env.STELLAR_ASSET_ISSUER
});
return {
transactionHash: result.hash,
status: 'success',
amount,
fromAddress,
toAddress
};
}
Stellar Configuration
Environment Settings
// Stellar settings configuration
interface StellarSettings {
ASSETCREATOR: string;
ASSETCODE: string;
NETWORK: 'TESTNET' | 'PUBLIC';
FAUCETSECRETKEY: string;
FUNDINGAMOUNT: string;
HORIZONURL: string;
BASEURL: string;
ADMINBASEURL: string;
EMAIL: string;
PASSWORD: string;
TENANTNAME: string;
}
Network Configuration
// Network-specific settings
const stellarNetworks = {
testnet: {
horizonUrl: 'https://horizon-testnet.stellar.org',
networkPassphrase: 'Test SDF Network ; September 2015',
assetIssuer: 'test-asset-issuer-address'
},
public: {
horizonUrl: 'https://horizon.stellar.org',
networkPassphrase: 'Public Global Stellar Network ; September 2015',
assetIssuer: 'production-asset-issuer-address'
}
};
2. EVM-Compatible Networks
Overview
EVM (Ethereum Virtual Machine) compatible networks provide alternative deployment options with extensive DeFi ecosystem integration and established tooling.
Supported Networks
1. Polygon (Amoy Testnet)
- Chain ID: 80002
- Currency: MATIC
- Block Time: ~2 seconds
- Gas Limit: 30M
- Features: Low fees, fast finality
2. Arbitrum (Sepolia Testnet)
- Chain ID: 421614
- Currency: ETH
- Block Time: ~1 second
- Gas Limit: 30M
- Features: Layer 2 scaling, low fees
3. Ethereum (Mainnet)
- Chain ID: 1
- Currency: ETH
- Block Time: ~12 seconds
- Gas Limit: 30M
- Features: Maximum security, established ecosystem
Smart Contracts (Solidity)
Contract Structure
// apps/contracts/src/contracts/AAProject.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract AAProject is ERC20, AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant TRIGGER_ROLE = keccak256("TRIGGER_ROLE");
mapping(bytes32 => Trigger) public triggers;
mapping(address => bool) public beneficiaries;
struct Trigger {
bool isActive;
uint256 threshold;
uint256 amount;
string conditions;
}
event TriggerExecuted(bytes32 indexed triggerId, address indexed beneficiary, uint256 amount);
event BeneficiaryAdded(address indexed beneficiary);
event TriggerCreated(bytes32 indexed triggerId, uint256 threshold, uint256 amount);
constructor() ERC20("Rahat Token", "RAHAT") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
}
function createTrigger(
bytes32 triggerId,
uint256 threshold,
uint256 amount,
string memory conditions
) external onlyRole(ADMIN_ROLE) {
triggers[triggerId] = Trigger(true, threshold, amount, conditions);
emit TriggerCreated(triggerId, threshold, amount);
}
function executeTrigger(bytes32 triggerId, address beneficiary) external onlyRole(TRIGGER_ROLE) {
require(triggers[triggerId].isActive, "Trigger not active");
require(beneficiaries[beneficiary], "Not a beneficiary");
uint256 amount = triggers[triggerId].amount;
_mint(beneficiary, amount);
emit TriggerExecuted(triggerId, beneficiary, amount);
}
function addBeneficiary(address beneficiary) external onlyRole(ADMIN_ROLE) {
beneficiaries[beneficiary] = true;
emit BeneficiaryAdded(beneficiary);
}
}
Contract Deployment
// apps/contracts/scripts/deploy.js
async function deployAAProject() {
const AAProject = await ethers.getContractFactory("AAProject");
const aaProject = await AAProject.deploy();
await aaProject.deployed();
console.log("AAProject deployed to:", aaProject.address);
return aaProject;
}
// Deploy to specific network
async function deployToNetwork(networkName) {
const network = await ethers.providers.getNetwork();
if (network.chainId === 80002) { // Polygon Amoy
console.log("Deploying to Polygon Amoy testnet");
} else if (network.chainId === 421614) { // Arbitrum Sepolia
console.log("Deploying to Arbitrum Sepolia testnet");
}
return await deployAAProject();
}
EVM Service Integration
Chain Service Implementation
// apps/aa/src/chain/chain-services/evm.service.ts
@Injectable()
export class EvmService implements IChainService {
private provider: ethers.providers.Provider;
private signer: ethers.Signer;
private contract: ethers.Contract;
constructor() {
this.provider = new ethers.providers.JsonRpcProvider(
process.env.NETWORK_PROVIDER
);
this.signer = new ethers.Wallet(
process.env.DEPLOYER_PRIVATE_KEY,
this.provider
);
}
async assignTokens(data: AssignTokensDto): Promise<any> {
const contract = new ethers.Contract(
process.env.CONTRACT_ADDRESS,
AAProjectABI,
this.signer
);
const tx = await contract.addBeneficiary(data.beneficiaryAddress);
await tx.wait();
return {
transactionHash: tx.hash,
status: 'success'
};
}
async transferTokens(data: TransferTokensDto): Promise<any> {
const contract = new ethers.Contract(
process.env.CONTRACT_ADDRESS,
AAProjectABI,
this.signer
);
const tx = await contract.transfer(
data.toAddress,
data.amount
);
await tx.wait();
return {
transactionHash: tx.hash,
status: 'success'
};
}
async disburse(data: DisburseDto): Promise<any> {
const contract = new ethers.Contract(
process.env.CONTRACT_ADDRESS,
AAProjectABI,
this.signer
);
const tx = await contract.executeTrigger(
data.triggerId,
data.beneficiaryAddress
);
await tx.wait();
return {
transactionHash: tx.hash,
status: 'success'
};
}
validateAddress(address: string): boolean {
return ethers.utils.isAddress(address);
}
getChainType(): ChainType {
return 'evm';
}
}
EVM Configuration
Environment Variables
# EVM Configuration
NETWORK_PROVIDER=https://polygon-amoy.infura.io/v3/YOUR_PROJECT_ID
CHAIN_NAME=Polygon Amoy
CHAIN_ID=80002
CURRENCY_NAME=MATIC
CURRENCY_SYMBOL=MATIC
DEPLOYER_PRIVATE_KEY=your_private_key
CONTRACT_ADDRESS=deployed_contract_address
Network Configuration
// Network configurations
const evmNetworks = {
polygonAmoy: {
name: 'Polygon Amoy',
chainId: 80002,
rpcUrl: 'https://polygon-amoy.infura.io/v3/YOUR_PROJECT_ID',
currency: 'MATIC',
explorer: 'https://www.oklink.com/amoy'
},
arbitrumSepolia: {
name: 'Arbitrum Sepolia',
chainId: 421614,
rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',
currency: 'ETH',
explorer: 'https://sepolia.arbiscan.io'
},
ethereum: {
name: 'Ethereum',
chainId: 1,
rpcUrl: 'https://mainnet.infura.io/v3/YOUR_PROJECT_ID',
currency: 'ETH',
explorer: 'https://etherscan.io'
}
};
Chain Selection Strategy
When to Use Stellar Soroban
Advantages
- Low Transaction Costs: ~0.00001 XLM per operation
- Fast Finality: 3-5 second transaction confirmation
- Native Asset Support: Built-in asset creation and management
- Emerging Markets: Better suited for developing regions
- Regulatory Compliance: Easier compliance in certain jurisdictions
Use Cases
- Micro-transactions: Small value transfers
- High-frequency Operations: Frequent trigger executions
- Cost-sensitive Applications: Where transaction costs matter
- Asset-backed Tokens: Native asset management
When to Use EVM Networks
Advantages
- DeFi Integration: Extensive DeFi ecosystem
- Established Tooling: Mature development tools
- Cross-chain Compatibility: Interoperability with other EVM chains
- Advanced Smart Contracts: Complex contract logic support
- Liquidity: Access to large liquidity pools
Use Cases
- Complex DeFi Operations: Advanced financial products
- Cross-chain Applications: Multi-chain interoperability
- Established Ecosystems: Integration with existing DeFi protocols
- High-value Transactions: Where security is paramount
Cross-Chain Operations
Chain Registry System
// apps/aa/src/chain/chain-queue-registry/chain-queue-registry.service.ts
@Injectable()
export class ChainQueueRegistryService {
private chainServices: Map<ChainType, IChainService> = new Map();
registerChain(chainType: ChainType, service: IChainService) {
this.chainServices.set(chainType, service);
}
getChainService(chainType: ChainType): IChainService {
const service = this.chainServices.get(chainType);
if (!service) {
throw new Error(`Chain service not found for type: ${chainType}`);
}
return service;
}
async executeOnChain(chainType: ChainType, operation: ChainOperation): Promise<any> {
const service = this.getChainService(chainType);
switch (operation.type) {
case 'TRANSFER_TOKENS':
return service.transferTokens(operation.data);
case 'DISBURSE':
return service.disburse(operation.data);
case 'FUND_ACCOUNT':
return service.fundAccount(operation.data);
default:
throw new Error(`Unknown operation type: ${operation.type}`);
}
}
}
Multi-Chain Configuration
// apps/aa/src/chain/chain-queue-registry/chain-queue-registry.module.ts
@Module({
imports: [
StellarModule,
EvmModule,
BullModule.registerQueue({
name: BQUEUE.CHAIN_OPERATIONS,
}),
],
providers: [
ChainQueueRegistryService,
{
provide: 'CHAIN_SERVICES',
useFactory: (
stellarService: StellarService,
evmService: EvmService,
registryService: ChainQueueRegistryService
) => {
registryService.registerChain('stellar', stellarService);
registryService.registerChain('evm', evmService);
return registryService;
},
inject: [StellarService, EvmService, ChainQueueRegistryService],
},
],
exports: [ChainQueueRegistryService],
})
export class ChainQueueRegistryModule {}
Security Considerations
Private Key Management
// Secure private key handling
interface KeyManagement {
stellar: {
adminSecretKey: string; // Stored securely
assetIssuerSecretKey: string;
};
evm: {
deployerPrivateKey: string; // Stored securely
adminPrivateKey: string;
};
}
Transaction Signing
// Secure transaction signing
async signTransaction(transaction: any, chainType: ChainType): Promise<any> {
switch (chainType) {
case 'stellar':
return this.signStellarTransaction(transaction);
case 'evm':
return this.signEvmTransaction(transaction);
default:
throw new Error(`Unsupported chain type: ${chainType}`);
}
}
Monitoring and Analytics
Blockchain Metrics
interface BlockchainMetrics {
stellar: {
totalTransactions: number;
averageTransactionTime: number;
totalTokensIssued: number;
activeBeneficiaries: number;
};
evm: {
totalTransactions: number;
gasUsed: number;
averageGasPrice: number;
contractInteractions: number;
};
}
Transaction Monitoring
async monitorTransaction(transactionHash: string, chainType: ChainType) {
const service = this.getChainService(chainType);
return {
hash: transactionHash,
status: await service.getTransactionStatus(transactionHash),
confirmations: await service.getConfirmations(transactionHash),
timestamp: await service.getTransactionTimestamp(transactionHash)
};
}
Testing
Unit Tests
describe('Chain Services', () => {
it('should transfer tokens on Stellar', async () => {
const result = await stellarService.transferTokens({
fromAddress: 'GABC123456789',
toAddress: 'GDEF987654321',
amount: 1000,
assetCode: 'RAHAT'
});
expect(result.status).toBe('success');
expect(result.transactionHash).toBeDefined();
});
it('should execute trigger on EVM', async () => {
const result = await evmService.disburse({
triggerId: 'flood-warning-001',
beneficiaryAddress: '0x1234567890abcdef'
});
expect(result.status).toBe('success');
expect(result.transactionHash).toBeDefined();
});
});