Free & open source — no account required
Free & open source — no account required
This technical guide provides an in-depth analysis of the swift to typescript engine, best practices for implementation, and data security standards.
Unlock the full power of the FinFlow Pro workbench. Specifically designed for FIX, SWIFT MT/MX, and ISO 20022 message inspection with industrial-grade accuracy.
Launch FinFlow ProSWIFT MT (Message Type) is the financial industry's ISO 15022 tag-value format for cross-border payments, securities settlement, and correspondent banking. Converting SWIFT MT to TypeScript type definitions requires understanding the block envelope (blocks 1–5 wrap every message), tagged field format (:32A:240315USD15000,00 = value date, currency, amount in a single field), and the coexistence period where MT and ISO 20022 MX messages run in parallel until the 2025 full cutover. This guide covers TypeScript interfaces for MT103/MT202/MT940, field format parsing, and how to migrate to MX types during the transition window.
// Every SWIFT MT message has this block structure:
// {1:F01BARCGB22AXXX0000000000} — Basic Header (sender BIC)
// {2:O1031000240315BNPAFRPPAXXX...} — Application Header (message type, receiver BIC)
// {3:{108:USER-REF-001}} — User Header (optional)
// {4: — Text Block (the actual payload)
// :20:REF20240315001
// :23B:CRED
// :32A:240315USD15000,00
// ...
// -}
// {5:{CHK:3B9E3FCBCFAC}} — Trailer (checksum)
// TypeScript interfaces for block parsing
export interface SwiftMtMessage {
basicHeader: BasicHeader;
applicationHeader: ApplicationHeader;
userHeader?: UserHeader;
trailer: MtTrailer;
}
export interface BasicHeader {
applicationId: string; // 'F' = FIN, 'A' = ACK
serviceId: string; // '01' = FIN/GPA, '21' = ack
logicalTerminalAddr: string; // 12-char BIC+branch: BARCGB22AXXX
sessionNumber: string; // 4 digits
sequenceNumber: string; // 6 digits
}
export interface ApplicationHeader {
ioIndicator: 'I' | 'O'; // Input (sent to SWIFT) or Output (received from SWIFT)
messageType: string; // '103', '202', '940', etc.
receiverBic?: string; // for Input messages: target BIC
senderBic?: string; // for Output messages: originator BIC
priority?: 'N' | 'U' | 'S'; // Normal, Urgent, System
}
export interface UserHeader {
serviceTypeId?: string; // tag 103 — 'CAT' for SWIFTNet Cash Reporting
messageUserReference?: string; // tag 108 — user-assigned reference
uniqueEndToEndTransactionRef?: string; // tag 121 — UETR (UUID), required post-2020
sanctionsScreeningInfo?: string; // tag 165 — OFAC/SWIFT compliance
}
export interface MtTrailer {
checksum?: string; // CHK: 12-char hash
possibleDuplicate?: string; // PDE: timestamp — resent message flag
duplicateMessage?: string; // DLM: delayed message flag
trainingMode?: string; // TNG: test message (never process as live)
systemOriginatedMessage?: string; // SYS: SWIFT network-generated
}
// MT103 text block field specifications (SWIFT notation → TypeScript)
// SWIFT format: 6!n = exactly 6 digits, 3!a = exactly 3 letters, 15d = up to 15 digits
export interface Mt103TextBlock {
// :20: 16x — 16-char alphanumeric, Transaction Reference Number
transactionReference: string;
// :23B: 4!a — Bank Operation Code: CRED, CRTS, SPAY, SSTD, SPRI
bankOperationCode: BankOperationCode;
// :32A: 6!n3!a15d — Value Date (YYMMDD) + Currency (ISO 4217) + Amount (comma decimal)
valueDate: Date;
currency: string; // ISO 4217: 'USD', 'EUR', 'GBP'
amount: string; // stored as string: '15000,00' → '15000.00'
// :33B: 3!a15d — Currency/Instructed Amount (if different from settlement amount)
instructedAmount?: { currency: string; amount: string };
// :50K/50A/50F: 34x / BIC / structured — Ordering Customer
orderingCustomer?: SwiftParty;
// :52A/52D: BIC / 35x — Ordering Institution
orderingInstitution?: SwiftParty;
// :53A/53B/53D: BIC / 35x / name — Sender's Correspondent
sendersCorrespondent?: SwiftParty;
// :54A/54B/54D: — Receiver's Correspondent
receiversCorrespondent?: SwiftParty;
// :56A/56D: — Intermediary Institution
intermediaryInstitution?: SwiftParty;
// :57A/57B/57C/57D: — Account With Institution (beneficiary's bank)
accountWithInstitution?: SwiftParty;
// :59/59A/59F: 34x / BIC / structured — Beneficiary Customer
beneficiaryCustomer: SwiftParty;
// :70: 4*35x — Remittance Information (4 lines × 35 chars each)
remittanceInfo?: string;
// :71A: 3!a — Details of Charges: SHA, OUR, BEN
detailsOfCharges: ChargesCode;
// :71F: 3!a15d — Sender's Charges
sendersCharges?: { currency: string; amount: string }[];
// :71G: 3!a15d — Receiver's Charges
receiversCharges?: { currency: string; amount: string };
// :72: 6*35x — Sender to Receiver Information (/INS/, /INT/, /RETN/, etc.)
senderToReceiver?: string;
}
export enum BankOperationCode { CRED = 'CRED', CRTS = 'CRTS', SPAY = 'SPAY', SSTD = 'SSTD', SPRI = 'SPRI' }
export enum ChargesCode { SHA = 'SHA', OUR = 'OUR', BEN = 'BEN' }
export interface SwiftParty {
optionQualifier: 'A' | 'B' | 'C' | 'D' | 'F' | 'K' | '';
accountNumber?: string; // /IBAN or /AccountNumber prefix
bic?: string; // for option A
name?: string;
address?: string[];
countryCode?: string;
}
// MT202: General Financial Institution Transfer (interbank, no customer data)
export interface Mt202TextBlock {
transactionReference: string; // :20:
relatedReference: string; // :21: — reference of the related MT103
valueDate: Date; // :32A:
currency: string;
amount: string;
orderingInstitution?: SwiftParty; // :52A/:52D:
sendersCorrespondent?: SwiftParty; // :53A/:53B/:53D:
receiversCorrespondent?: SwiftParty; // :54A/:54B/:54D:
beneficiaryInstitution: SwiftParty; // :58A/:58D: — required field
senderToReceiver?: string; // :72:
}
// MT940: Customer Statement Message (used for bank statement delivery)
export interface Mt940TextBlock {
transactionReference: string; // :20:
relatedReference?: string; // :21:
accountId: string; // :25: — IBAN or account number
statementNumber: string; // :28C: statement number/sequence
openingBalance: Mt940Balance; // :60F:/:60M: first or subsequent
transactions: Mt940Transaction[]; // :61: entries
closingBalance: Mt940Balance; // :62F:/:62M:
closingAvailableBalance?: Mt940Balance; // :64:
forwardAvailableBalance?: Mt940Balance[]; // :65:
informationToAccountOwner?: string; // :86: narrative
}
export interface Mt940Balance {
creditDebit: 'C' | 'D' | 'RC' | 'RD'; // Credit/Debit/Reversed Credit/Reversed Debit
date: Date;
currency: string;
amount: string;
}
export interface Mt940Transaction {
valueDate: Date; // :61: first 6 chars YYMMDD
entryDate?: string; // :61: optional 4 chars MMDD
creditDebit: 'C' | 'D' | 'RC' | 'RD';
fundsCode?: string; // 3rd char (D=domestic, S=SWIFT, etc.)
amount: string;
transactionType: string; // S= (SWIFT), N= (non-SWIFT), F= (first advice)
referenceForAccountOwner: string; // customer reference
referenceForBank?: string; // bank reference after //
supplementaryDetails?: string; // :86: — free text narrative
}
// During the coexistence period (2023-2025), both MT and MX messages flow in parallel.
// SWIFT Translator Service converts between them, but you must understand the mapping.
// MT103 field → ISO 20022 pacs.008 element mapping:
// :20: TransactionReference → GrpHdr/MsgId or CdtTrfTxInf/PmtId/InstrId
// :32A: ValueDate/Currency/Amount → CdtTrfTxInf/IntrBkSttlmAmt + IntrBkSttlmDt
// :50K: OrderingCustomer → CdtTrfTxInf/Dbtr (Debtor)
// :59: BeneficiaryCustomer → CdtTrfTxInf/Cdtr (Creditor)
// :70: RemittanceInfo → CdtTrfTxInf/RmtInf/Ustrd (unstructured)
// :71A: DetailsOfCharges → CdtTrfTxInf/ChrgBr (SHA=SLEV, OUR=DEBT, BEN=CRED)
// Truncation risk: ISO 20022 allows longer strings than MT.
// MT :50K: name field = 4×35 chars max. MX Debtor/Nm = 140 chars.
// When translating MX→MT, names over 35 chars are truncated — data loss!
// TypeScript migration helper: generate both MT and MX representations
import { Decimal } from 'decimal.js';
interface Mt103Data {
transactionReference: string;
valueDate: Date;
currency: string;
amount: string;
orderingCustomer?: SwiftParty;
beneficiaryCustomer: SwiftParty;
remittanceInfo?: string;
detailsOfCharges: ChargesCode;
}
interface Pacs008Data {
msgId: string;
creDtTm: string; // ISO 8601
nbOfTxs: number;
intrBkSttlmAmt: { ccy: string; value: string };
intrBkSttlmDt: string; // YYYY-MM-DD
dbtr: { nm?: string; id?: { iban: string } };
cdtr: { nm?: string; id?: { iban: string } };
rmtInf?: { ustrd?: string };
chrgBr: 'DEBT' | 'SLEV' | 'CRED';
}
function mt103ToPacs008(mt: Mt103Data): Pacs008Data {
const chargesMap: Record<ChargesCode, 'DEBT' | 'SLEV' | 'CRED'> = {
OUR: 'DEBT', SHA: 'SLEV', BEN: 'CRED',
};
return {
msgId: mt.transactionReference,
creDtTm: new Date().toISOString(),
nbOfTxs: 1,
intrBkSttlmAmt: { ccy: mt.currency, value: mt.amount.replace(',', '.') },
intrBkSttlmDt: mt.valueDate.toISOString().slice(0, 10),
dbtr: { nm: mt.orderingCustomer?.name },
cdtr: { nm: mt.beneficiaryCustomer?.name },
rmtInf: mt.remittanceInfo ? { ustrd: mt.remittanceInfo } : undefined,
chrgBr: chargesMap[mt.detailsOfCharges],
};
}
15000,00 not 15000.00). JavaScript's parseFloat converts this correctly but number types lose precision for financial arithmetic. Store as string, replace comma with period, and use new Decimal(amountStr) for calculations.50A carries only a BIC, 50F is structured (name + structured address), 50K is free-form (name + address lines). A production parser must handle all three variants for the same logical field.{CHK:xxxxxxxx} is a 12-character checksum over the text block. Reject messages with missing or mismatched checksums — they indicate corruption or truncation in transit. The SWIFT network should prevent this, but downstream retransmission systems sometimes drop the trailer.Q: What is the difference between MT and MX (ISO 20022)?
A: MT (ISO 15022) uses a compact tag-value format with single-character field codes — originated in the 1970s telex era. MX (ISO 20022) uses XML with human-readable element names and richer structured data (structured postal addresses, LEI identifiers, purpose codes). The SWIFT network is migrating from MT to MX, with a mandatory cutover date for cross-border payments. MT and MX carry equivalent information for core payment fields but MX supports much richer remittance data (structured invoice references, regulatory codes).
Q: How do I handle SWIFT MT character set restrictions in TypeScript strings?
A: SWIFT's X character set (used in most name and address fields) allows only ASCII letters, digits, and the characters / - ? : ( ) . , ' + space CR LF. When building TypeScript types from SWIFT MT data, validate name and address fields with /^[A-Za-z0-9\/\-?:()\.,'+\n\r ]+$/. Characters outside this set cause message rejection by correspondent banks — common in European names with umlauts or Asian institution names.
Q: What npm packages exist for SWIFT MT parsing?
A: swift-parser and mt-parser on npm handle basic tag extraction. For full production use with field validation and multi-qualifier support, most banks implement custom parsers because the SWIFT MT specification has institution-specific extensions (tags above 99, custom subfield formats) that generic libraries don't cover. The official SWIFT Alliance toolkits are proprietary and require SWIFT membership.
Is the processing local-only?
Absolutely. TypeMorph operates entirely within your browser's sandbox. We use Web Workers for high-performance computation without ever transmitting your JSON, SQL, or API data to a remote server.
Can I use this for enterprise projects?
Yes. The tool is designed for professional software engineers who require GDPR compliance and data privacy. It is trusted by developers at top-tier startups and financial institutions.
Why pasting proprietary company data into third-party web tools is a major liability, and how to stay safe.
A deep dive into combining Zod, React Query, and TypeScript for bulletproof API integration.
Code generation is just the beginning. Discover how a schema-first approach can eliminate 90% of your integration bugs.