Metadata-Version: 2.4
Name: swiftlib
Version: 1.0.1
Summary: Python library for Swift MT and ISO 20022 message parsing and generation
Project-URL: Homepage, https://github.com/mahimaanu/swiftlib
Project-URL: Repository, https://github.com/mahimaanu/swiftlib
Project-URL: Bug Tracker, https://github.com/mahimaanu/swiftlib/issues
Author: Mahima
License: MIT
License-File: LICENSE
Keywords: banking,financial,iso20022,mt,payment,swift
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: lxml>=4.9
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

# swiftlib

[![PyPI version](https://img.shields.io/pypi/v/swiftlib.svg)](https://pypi.org/project/swiftlib/)
[![Python versions](https://img.shields.io/pypi/pyversions/swiftlib.svg)](https://pypi.org/project/swiftlib/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Python 3 library for parsing and generating SWIFT MT messages and ISO 20022 XML messages.

---

## Overview

**swiftlib** provides:

- **SWIFT MT parsing and generation** — full support for MT103, MT202, MT202COV, MT515, MT700, MT900, MT910, MT940, MT942, MT950
- **ISO 20022 XML parsing and generation** — pain.001, camt.053, pacs.008 (extensible to any message type)
- **MT ↔ ISO 20022 converters** — MT103 ↔ pain.001, MT103 ↔ pacs.008, MT940 ↔ camt.053
---


## Installation

**swiftlib** is available on [PyPI](https://pypi.org/project/swiftlib/):

```bash
pip install swiftlib
```

**Requirements**: Python 3.10+, lxml>=4.9, pydantic>=2.0

---

## Quick Start

### Parsing an MT103

```python
from swiftlib.mt import parse

raw = """{1:F01BANKBEBBAXXX0000000000}{2:I103BANKDEFFXXXXU}{4:
:20:FT21099B59YFW001
:23B:CRED
:32A:210101USD10000,
:50K:/12345678
JOHN DOE
123 MAIN ST
:59:/98765432
JANE SMITH
:70:PAYMENT FOR SERVICES
:71A:OUR
-}"""

msg = parse(raw)  # Returns a typed MT103 instance
print(msg.message_type)   # "103"
print(msg.amount)          # Decimal("10000")
print(msg.currency)        # "USD"
print(msg.value_date)      # date(2021, 1, 1)
print(msg.charges)         # "OUR"
```

### Building an MT103

```python
from swiftlib.mt.messages.mt103 import MT103Builder
from decimal import Decimal
from datetime import date

mt103 = (
    MT103Builder()
    .transaction_reference("FT21099B59YFW001")
    .bank_operation_code("CRED")
    .value_date_currency_amount(date(2021, 1, 1), "USD", Decimal("10000.00"))
    .ordering_customer("/12345678", "JOHN DOE", ["123 MAIN ST", "NEW YORK NY"])
    .account_with_institution("A", "BANKDEFF")
    .beneficiary("/98765432", "JANE SMITH", ["456 OAK AVE", "BERLIN 10115"])
    .remittance_info("PAYMENT FOR SERVICES")
    .charges("OUR")
    .build()
)

print(mt103.to_swift())
print(mt103.to_json())
```

### Parsing an ISO 20022 pain.001

```python
from swiftlib.iso20022 import parse

with open("payment.xml") as f:
    msg = parse(f.read())

print(msg.group_header.message_id)
print(msg.payment_information[0].debtor.name)
print(msg.payment_information[0].credit_transfer_transactions[0].amount.amount)
```

### Generating a pain.001

```python
from swiftlib.iso20022.messages.pain001 import (
    Pain001Builder, Party, PaymentInformation,
    CreditTransferTransaction, PaymentIdentification,
    InstructedAmount, AccountIdentification,
    BranchAndFinancialInstitutionIdentification,
    FinancialInstitutionIdentification,
)
from datetime import date, datetime
from decimal import Decimal

fi = FinancialInstitutionIdentification(bic="BANKDEFF")
agt = BranchAndFinancialInstitutionIdentification(financial_institution=fi)

tx = CreditTransferTransaction(
    payment_id=PaymentIdentification(end_to_end_id="E2E-001"),
    amount=InstructedAmount(currency="EUR", amount=Decimal("5000.00")),
    charge_bearer="SLEV",
    creditor_agent=agt,
    creditor=Party(name="BENEFICIARY"),
    creditor_account=AccountIdentification(iban="DE98765432109876543210"),
)

pi = PaymentInformation(
    payment_info_id="PI-001",
    payment_method="TRF",
    batch_booking=False,
    number_of_transactions=1,
    control_sum=Decimal("5000.00"),
    payment_type_info=None,
    requested_execution_date=date(2021, 1, 1),
    debtor=Party(name="PAYER"),
    debtor_account=AccountIdentification(iban="US12345678901234567890"),
    debtor_agent=agt,
    credit_transfer_transactions=[tx],
)

pain001 = (
    Pain001Builder()
    .message_id("MSG-001")
    .creation_datetime(datetime.now())
    .initiating_party(Party(name="MY COMPANY"))
    .add_payment_information(pi)
    .build()
)

xml = pain001.to_xml()
```

---

## Supported Message Types

### SWIFT MT

| Message Type | Description | Status |
|-------------|-------------|--------|
| MT103 | Single Customer Credit Transfer | Full |
| MT202 | General Financial Institution Transfer | Full |
| MT202COV | General FI Transfer (Cover) | Full |
| MT515 | Client Confirmation of Purchase/Sale | Full |
| MT700 | Issue of a Documentary Credit | Full |
| MT900 | Confirmation of Debit | Full |
| MT910 | Confirmation of Credit | Full |
| MT940 | Customer Statement Message | Full |
| MT942 | Interim Transaction Report | Full |
| MT950 | Statement Message | Full |

### ISO 20022

| Message Type | Description | Status |
|-------------|-------------|--------|
| pain.001.001.09 | Customer Credit Transfer Initiation | Full |
| pain.001.001.03 | Customer Credit Transfer Initiation (v3) | Supported |
| camt.053.001.08 | Bank to Customer Statement | Full |
| camt.053.001.02 | Bank to Customer Statement (v2) | Supported |
| pacs.008.001.08 | FI to FI Customer Credit Transfer | Full |
| pacs.008.001.02 | FI to FI Customer Credit Transfer (v2) | Supported |

---

## API Reference Highlights

### swiftlib.mt

```python
from swiftlib.mt import parse, MT103, MT940, MT202

# Parse any MT message (returns typed instance)
msg = parse(raw_swift_string)

# Parse specifically as MT103
mt103 = MT103.from_swift(raw)

# Typed property access
mt103.transaction_reference  # str
mt103.value_date             # datetime.date
mt103.currency               # str
mt103.amount                 # Decimal
mt103.charges                # "OUR" | "SHA" | "BEN"
mt103.ordering_customer      # str (multiline)
mt103.beneficiary            # str (multiline)

# Validation
errors = mt103.validate()    # list[str]
mt103.is_valid()             # bool

# Serialisation
mt103.to_swift()             # SWIFT FIN string
mt103.to_dict()              # dict
mt103.to_json()              # JSON string
```

### swiftlib.iso20022

```python
from swiftlib.iso20022 import ISO20022Parser, ISO20022Generator

parser = ISO20022Parser()
msg = parser.parse(xml_string)          # auto-detect type
msg = parser.parse_file("payment.xml")  # from file

generator = ISO20022Generator()
xml = generator.generate(pain001)       # str
xml_bytes = generator.generate_bytes(pain001)  # bytes
```

### swiftlib.converters

```python
from swiftlib.converters import (
    MT103ToPain001Converter,
    MT103ToPacs008Converter,
    MT940ToCamt053Converter,
    Pain001ToMT103Converter,
    Pacs008ToMT103Converter,
)

# MT103 → pain.001
pain001 = MT103ToPain001Converter().convert(mt103)

# MT103 → pacs.008
pacs008 = MT103ToPacs008Converter().convert(mt103)

# pain.001 → list[MT103]
mt103_list = Pain001ToMT103Converter().convert(pain001)

# MT940 → camt.053
camt053 = MT940ToCamt053Converter().convert(mt940)
```

---

## Conversion

```python
from swiftlib.mt import MT103
from swiftlib.converters import MT103ToPain001Converter, Pain001ToMT103Converter

# Parse MT103
mt103 = MT103.from_swift(raw_mt103)

# Convert to pain.001
pain001 = MT103ToPain001Converter().convert(mt103)
xml = pain001.to_xml()

# Convert back to MT103
mt103_list = Pain001ToMT103Converter().convert(pain001)
restored = mt103_list[0]
print(restored.to_swift())
```

---

## Integration Examples

### FastAPI

```python
from fastapi import FastAPI, HTTPException
from swiftlib.mt import parse
from swiftlib.exceptions import ParseError

app = FastAPI()

@app.post("/parse-mt")
async def parse_mt(body: str):
    try:
        msg = parse(body)
        return msg.to_dict()
    except ParseError as e:
        raise HTTPException(status_code=400, detail=str(e))

@app.post("/convert/mt103-to-xml")
async def convert_mt103_to_xml(body: str):
    from swiftlib.mt.messages.mt103 import MT103
    from swiftlib.converters import MT103ToPain001Converter
    mt103 = MT103.from_swift(body)
    pain001 = MT103ToPain001Converter().convert(mt103)
    return {"xml": pain001.to_xml()}
```

### Django

```python
# views.py
from django.http import JsonResponse, HttpRequest
from swiftlib.mt import parse

def parse_swift(request: HttpRequest) -> JsonResponse:
    raw = request.body.decode("utf-8")
    try:
        msg = parse(raw)
        return JsonResponse(msg.to_dict())
    except Exception as e:
        return JsonResponse({"error": str(e)}, status=400)
```


---

## Building from Source

```bash
git clone https://github.com/mahimaanu/swiftlib.git
cd swiftlib
pip install -e ".[dev]"
```

---

## License

MIT License. See [LICENSE](LICENSE) for details.
