🌿
Mother Earth CryingClimate Awareness · OECS
ECCB Single Gateway27 ECCU Licensed Financial InstitutionsDCash 2.0 CBDC

ECCB Single Gateway Integration Hub

One integration point. All 27 Licensed Financial Institutions across 8 ECCU territories. Built on the ECCB's Instant Payment System (IPS) data rail, aligned with the Greening the Financial System initiative and the Payment System and Services Act 2025/2026.

🌎
8
ECCU Member Territories
🏦
27
Licensed Financial Institutions
ISO 20022
ECCB IPS Data Rail
💎
DCash 2.0
CBDC
⚖️
PSSA 2025/26
Legal Basis
🌿
Jul 2024
Climate Standard
ECCB Single Gateway Architecture1 integration → 27 banks
🏦
27 ECCU LFIs
8 territories
ECCB IPS Hub
ISO 20022 clearinghouse
🔍
GCFT ISO Listener
Purpose Code filter
📊
GCFT MRV Dashboard
Regional Heatmap
📋
GCF / ECCB Reports
Quarterly PDF
Strategic advantage: The ECCB has sole responsibility for payment and settlement systems across all 8 ECCU territories. A single integration with the ECCB IPS hub gives the GCFT Platform access to all 27 Licensed Financial Institutions simultaneously — bypassing individual bank negotiations for data access.
ISO 20022 Purpose Code → GCF Category Mapping
Purpose CodeLabelGCF CategoryRio MarkerStatus
ENRGEnergy / Solar PVMitigation — Renewable EnergyMarker 2✅ Tracked
AGRIAgriculture / CSAAdaptation — Food SecurityMarker 1✅ Tracked
HLTHWater & HealthAdaptation — Water ResourcesMarker 2✅ Tracked
TRADEV Fleet / TransportMitigation — TransportMarker 2✅ Tracked
OTHRResilient HousingAdaptation — InfrastructureMarker 2✅ Tracked
CORTGeneral CommercialNon-Climate (Flagged)Marker 0⏭ Skipped
ECCU Green Capital Flow HeatmapLive ISO 20022 Feed
🇦🇬
Antigua & Barbuda
4 banks
0
green txns
MVI 72/100
🇩🇲
Dominica
3 banks
0
green txns
MVI 97/100
🇬🇩
Grenada
4 banks
0
green txns
MVI 85/100
🇰🇳
St Kitts & Nevis
1 banks
0
green txns
MVI 68/100
🇱🇨
Saint Lucia
5 banks
0
green txns
MVI 79/100
🇻🇨
St Vincent & Gren.
4 banks
0
green txns
MVI 81/100
🇲🇸
Montserrat
4 banks
0
green txns
MVI 88/100
🇦🇮
Anguilla
2 banks
0
green txns
MVI 65/100
Simulating ISO 20022 pacs.008 Purpose Code filtering across 27 ECCU Licensed Financial Institutions via ECCB IPS hub
eccb-ips-green-listener.py
Python · asyncio · websockets · mTLS
"""
GCFT Platform — ECCB IPS ISO 20022 Green Finance Listener
Connects to ECCB Payment System Hub via secure WebSocket (mTLS)
Filters transactions by ISO 20022 Purpose Code for climate-tagged loans
Pushes anonymized metadata to GCFT Regional MRV Dashboard

Legal basis: Payment System and Services Act 2025/2026 (ECCU)
Security:    mTLS X.509 + HMAC-SHA256 payload signing
Data:        PII masked per ECCB Data Protection Guidelines
"""

import asyncio, json, hashlib, hmac, os
from datetime import datetime, timezone
import websockets

ECCB_IPS_WS_URL   = "wss://ips.eccb-centralbank.org/v1/transactions/stream"
GCFT_MRV_ENDPOINT = "https://api.gcftportal.org/api/v1/mrv/ingest"
MTLS_CERT         = "/etc/gcft/certs/client.crt"
MTLS_KEY          = "/etc/gcft/certs/client.key"
ECCB_CA_BUNDLE    = "/etc/gcft/certs/eccb-ca.crt"

# ISO 20022 Purpose Codes mapped to GCF categories
GREEN_PURPOSE_CODES = {
    "ENRG": {"gcf": "Mitigation — Renewable Energy",  "rio": "2"},
    "AGRI": {"gcf": "Adaptation — Food Security",     "rio": "1"},
    "HLTH": {"gcf": "Adaptation — Water Resources",   "rio": "2"},
    "TRAD": {"gcf": "Mitigation — Transport",         "rio": "2"},
    "OTHR": {"gcf": "Adaptation — Infrastructure",    "rio": "2"},
}

def mask_pii(account_id: str) -> str:
    """SHA-256 hash of account ID — irreversible, ECCB-compliant"""
    return hashlib.sha256(account_id.encode()).hexdigest()[:16]

def sign_payload(payload: dict, secret: str) -> str:
    """HMAC-SHA256 signature for GCF audit trail"""
    msg = json.dumps(payload, sort_keys=True).encode()
    return hmac.new(secret.encode(), msg, hashlib.sha256).hexdigest()

async def process_transaction(tx: dict):
    """Parse ISO 20022 pacs.008 message and push to GCFT MRV"""
    purp_code = tx.get("PurpCd", "")
    if purp_code not in GREEN_PURPOSE_CODES:
        return  # Non-climate transaction — skip

    mapping = GREEN_PURPOSE_CODES[purp_code]
    payload = {
        "msgId":      tx["MsgId"],
        "txId":       tx["TxId"],
        "bankBIC":    tx["DbtrAgt"]["FinInstnId"]["BICFI"],   # Bank BIC code
        "territory":  tx["DbtrAgt"]["FinInstnId"]["BICFI"][:2],  # 2-char territory
        "amtXCD":     float(tx["IntrBkSttlmAmt"]["#text"]),
        "amtUSD":     float(tx["IntrBkSttlmAmt"]["#text"]) / 2.7,  # ECCB fixed peg
        "purposeCode": purp_code,
        "gcfCategory": mapping["gcf"],
        "rioMarker":   mapping["rio"],
        "borrowerRef": mask_pii(tx["Cdtr"]["Acct"]["Id"]["Othr"]["Id"]),
        "timestamp":   datetime.now(timezone.utc).isoformat(),
    }

    sig = sign_payload(payload, os.environ["GCFT_HMAC_SECRET"])
    import aiohttp
    async with aiohttp.ClientSession() as session:
        await session.post(
            GCFT_MRV_ENDPOINT,
            json=payload,
            headers={
                "Authorization": f"Bearer {os.environ['GCFT_API_KEY']}",
                "X-GCFT-Signature": sig,
                "X-ISO20022-MsgType": "pacs.008.001.08",
                "X-ECCB-Territory": payload["territory"],
            },
            ssl=True
        )
    print(f"[GCFT] ✅ Green tx ingested: {purp_code} | {payload['territory']} | XCD {payload['amtXCD']:,.0f}")

async def listen_eccb_ips():
    """Main listener — connects to ECCB IPS WebSocket stream"""
    import ssl
    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ssl_ctx.load_cert_chain(MTLS_CERT, MTLS_KEY)
    ssl_ctx.load_verify_locations(ECCB_CA_BUNDLE)

    print("[GCFT] Connecting to ECCB IPS stream...")
    async with websockets.connect(ECCB_IPS_WS_URL, ssl=ssl_ctx) as ws:
        print("[GCFT] ✅ Connected to ECCB IPS. Listening for Green Finance codes...")
        async for message in ws:
            tx = json.loads(message)
            await process_transaction(tx)

if __name__ == "__main__":
    asyncio.run(listen_eccb_ips())