MoonBit ISO 20022 validation, status timeline, statement audit and reconciliation toolkit.
moon add cstoooo/moonpay_flow@0.8.2import {
"cstoooo/moonpay_flow" @moonpay_flow,
}moon check
moon test
moon run cmd/main -- fixtures/valid_pain001.xml
moon run cmd/main -- --format json fixtures/valid_pain001.xml
moon run cmd/main -- --list-rulesscripts/check.sh| Command | Purpose |
|---|---|
| <message.xml> | Validate one supported ISO 20022 message |
| reconcile <pain.001> <status> | Match payment instructions with status entries |
| lifecycle <payment> <status> <statement> | Compact payment, status and posting summary |
| audit <camt.053> | Single-account balance and duplicate-entry audit |
| audit-portfolio <camt.053> | Audit every Stmt and account separately |
| timeline <payment> [status ...] | Merge multiple status reports by timestamp |
| return-ledger <payment> <statement ...> | Authoritative cross-period refund/reversal ledger |
| --list-rules | Print all 82 rule codes and descriptions |
moon run cmd/main -- --format text fixtures/valid_pain001.xml
moon run cmd/main -- --format json fixtures/valid_pain001.xml
moon run cmd/main -- --format markdown fixtures/invalid_pain001.xmlmoon run cmd/main -- return-ledger \
fixtures/returns_pain001.xml \
fixtures/returns_day1.xml \
fixtures/returns_day2_partial.xml \
fixtures/returns_day3_final.xml \
fixtures/returns_day4_refund_reversal.xml2026-10-01 DBIT 100.00 original payment
2026-10-02 CRDT 20.00 partial refund
2026-10-03 CRDT 80.00 final refund
2026-10-04 DBIT 80.00 reversal of the final refundstate=PARTIALLY_RETURNED
Posted payment: 100.00
Effective refund: 20.00
Remaining: 80.00let validation = @moonpay_flow.validate_message(xml_text)
let timeline = @moonpay_flow.status_timeline_report(payment_xml, status_xmls)
let portfolio = @moonpay_flow.statement_portfolio_audit(camt_xml)
let ledger = @moonpay_flow.return_ledger_report(payment_xml, statement_xmls)| Message | Supported version |
|---|---|
| pain.001 | pain.001.001.03 |
| pain.002 | pain.002.001.03 |
| pacs.008 | pacs.008.001.08 |
| pacs.002 | pacs.002.001.10 |
| camt.053 | camt.053.001.08 |
pub(all) suberror XmlParseError {
XmlParseError(String)
}pub struct Decimal {
minor_units : Int
scale : Int
}pub struct Diagnostic {
code : String
path : String
message : String
}pub struct DuplicateStatementEntry {
end_to_end_id : String
amount : Decimal
currency : String
account_iban : String?
credit_debit : String
reversal : Bool
occurrences : Int
}pub(all) enum LedgerLegKind {
OriginalPayment
RefundCredit
ReversalOfPayment
ReversalOfRefund
UnlinkedReversal
}pub(all) enum LedgerLinkQuality {
LedgerExplicitLink
LedgerInferredLink
LedgerAmbiguousLink
LedgerMissingLink
}pub struct LifecycleCase {
end_to_end_id : String
amount : Decimal
currency : String
debtor_iban : String?
creditor_iban : String?
status : String?
statement_role : String
net_posted : Decimal?
reversal_count : Int
state : LifecycleState
action : String
}pub struct LifecycleReport {
cases : Array[LifecycleCase]
orphan_statuses : Array[String]
orphan_statements : Array[String]
}pub(all) enum LifecycleState {
Settled
SettledNotPosted
Rejected
Pending
MissingStatus
StatementMismatch
StatementBeforeFinalStatus
PartiallyRefunded
FullyRefunded
AccountUnmatched
}pub struct MessageInfo {
kind : MessageKind
message_id : String?
creation_datetime : String?
original_message_id : String?
entry_count : Int
}pub(all) enum MessageKind {
Pain001
Pain002
Pacs008
Pacs002
Camt053
Unknown
}pub struct Pain001Summary {
message_id : String?
creation_datetime : String?
payment_instruction_count : Int
transaction_count : Int
}pub struct PaymentRecord {
end_to_end_id : String
amount : Decimal
currency : String
debtor_iban : String?
creditor_iban : String?
}pub struct ReturnLedgerCase {
end_to_end_id : String
declared_amount : Decimal
currency : String
account_role : String
state : ReturnLedgerState
observed_payment : Decimal
observed_refund : Decimal
posted_payment : Decimal?
effective_refund : Decimal?
remaining : Decimal?
crossed_period : Bool
legs : Array[ReturnLedgerLeg]
issues : Array[LedgerIssue]
action : String
}pub struct ReturnLedgerLeg {
statement_id : String?
booking_date : String?
entry_reference : String?
transaction_id : String?
uetr : String?
original_entry_reference : String?
original_transaction_id : String?
amount : Decimal
currency : String
credit_debit : String
reversal : Bool
kind : LedgerLegKind
linked_to : String?
link_quality : LedgerLinkQuality
}pub struct ReturnLedgerReport {
statement_count : Int
cases : Array[ReturnLedgerCase]
orphan_entries : Array[ReturnLedgerLeg]
diagnostics : Array[Diagnostic]
}pub(all) enum ReturnLedgerState {
LedgerNotPosted
LedgerPaid
LedgerPartiallyReturned
LedgerFullyReturned
LedgerPaymentReversed
LedgerEvidenceIncomplete
LedgerConflict
}pub struct StatementAuditReport {
statement_id : String?
account_iban : String?
account_count : Int
entry_count : Int
total_credits : Decimal
total_debits : Decimal
net_movement : Decimal
opening_balance : StatementBalance?
closing_balance : StatementBalance?
expected_closing : Decimal?
closing_difference : Decimal?
balance_status : StatementBalanceStatus
duplicate_entries : Array[DuplicateStatementEntry]
diagnostics : Array[Diagnostic]
}pub(all) enum StatementBalanceStatus {
Balanced
BalanceMismatch
BalanceIncomplete
}pub struct StatementPortfolioReport {
message_id : String?
statements : Array[StatementAuditReport]
diagnostics : Array[Diagnostic]
}pub struct StatementRecord {
statement_id : String?
entry_reference : String?
transaction_id : String?
uetr : String?
original_entry_reference : String?
original_transaction_id : String?
booking_date : String?
end_to_end_id : String
amount : Decimal
currency : String
account_iban : String?
credit_debit : String
reversal : Bool
}pub struct StatusEventRecord {
message_id : String?
creation_datetime : String?
end_to_end_id : String
status : String
reason_code : String?
original_amount : Decimal?
original_currency : String?
}pub struct StatusTimelineCase {
end_to_end_id : String
amount : Decimal
currency : String
events : Array[StatusEventRecord]
latest_status : String?
state : TimelineState
issues : Array[TimelineIssue]
action : String
}pub struct StatusTimelineReport {
message_count : Int
event_count : Int
cases : Array[StatusTimelineCase]
orphan_status_ids : Array[String]
orphan_events : Array[StatusEventRecord]
diagnostics : Array[Diagnostic]
}pub(all) enum TimelineSeverity {
TimelineInfo
TimelineWarning
TimelineError
}pub(all) enum TimelineState {
TimelineAwaiting
TimelineInProgress
TimelineSettled
TimelineRejected
TimelineConflict
TimelineUnknown
}fn lifecycle_report(pain_xml : String, status_xml : String, statement_xml : String) -> LifecycleReport raise XmlParseErrorfn reconcile_pain001_status(pain_xml : String, status_xml : String) -> ReconciliationReport raise XmlParseErrorfn return_ledger_report(payment_xml : String, statement_xmls : Array[String]) -> ReturnLedgerReport raise XmlParseErrorfn status_timeline_report(payment_xml : String, status_xmls : Array[String]) -> StatusTimelineReport raise XmlParseErrorInstall
Download zipMoonBit ISO 20022 validation, status timeline, statement audit and reconciliation toolkit.