@coderoftime/fints 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE +28 -0
- package/README.md +156 -2
- package/dist/core/account.d.ts +140 -0
- package/dist/core/account.d.ts.map +1 -0
- package/dist/core/account.js +174 -0
- package/dist/core/account.js.map +1 -0
- package/dist/core/amount.d.ts +62 -0
- package/dist/core/amount.d.ts.map +1 -0
- package/dist/core/amount.js +189 -0
- package/dist/core/amount.js.map +1 -0
- package/dist/core/balance.d.ts +54 -0
- package/dist/core/balance.d.ts.map +1 -0
- package/dist/core/balance.js +53 -0
- package/dist/core/balance.js.map +1 -0
- package/dist/core/bank-info.d.ts +49 -0
- package/dist/core/bank-info.d.ts.map +1 -0
- package/dist/core/bank-info.js +52 -0
- package/dist/core/bank-info.js.map +1 -0
- package/dist/core/client.d.ts +126 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +2 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/config.d.ts +68 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +113 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/errors.d.ts +91 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +182 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/feedback.d.ts +69 -0
- package/dist/core/feedback.d.ts.map +1 -0
- package/dist/core/feedback.js +124 -0
- package/dist/core/feedback.js.map +1 -0
- package/dist/core/transaction.d.ts +98 -0
- package/dist/core/transaction.d.ts.map +1 -0
- package/dist/core/transaction.js +91 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/transport.d.ts +37 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +92 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/formats/camt.d.ts +12 -0
- package/dist/formats/camt.d.ts.map +1 -0
- package/dist/formats/camt.js +159 -0
- package/dist/formats/camt.js.map +1 -0
- package/dist/formats/mt940.d.ts +42 -0
- package/dist/formats/mt940.d.ts.map +1 -0
- package/dist/formats/mt940.js +297 -0
- package/dist/formats/mt940.js.map +1 -0
- package/dist/formats/readers.d.ts +11 -0
- package/dist/formats/readers.d.ts.map +1 -0
- package/dist/formats/readers.js +47 -0
- package/dist/formats/readers.js.map +1 -0
- package/dist/formats/sepa-purpose.d.ts +22 -0
- package/dist/formats/sepa-purpose.d.ts.map +1 -0
- package/dist/formats/sepa-purpose.js +68 -0
- package/dist/formats/sepa-purpose.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/session/app-approval.d.ts +60 -0
- package/dist/session/app-approval.d.ts.map +1 -0
- package/dist/session/app-approval.js +215 -0
- package/dist/session/app-approval.js.map +1 -0
- package/dist/session/bank-connection.d.ts +28 -0
- package/dist/session/bank-connection.d.ts.map +1 -0
- package/dist/session/bank-connection.js +48 -0
- package/dist/session/bank-connection.js.map +1 -0
- package/dist/session/dialog-runner.d.ts +34 -0
- package/dist/session/dialog-runner.d.ts.map +1 -0
- package/dist/session/dialog-runner.js +112 -0
- package/dist/session/dialog-runner.js.map +1 -0
- package/dist/session/login-guard.d.ts +73 -0
- package/dist/session/login-guard.d.ts.map +1 -0
- package/dist/session/login-guard.js +109 -0
- package/dist/session/login-guard.js.map +1 -0
- package/dist/session/parameter-data.d.ts +83 -0
- package/dist/session/parameter-data.d.ts.map +1 -0
- package/dist/session/parameter-data.js +68 -0
- package/dist/session/parameter-data.js.map +1 -0
- package/dist/session/pin-tan-client.d.ts +54 -0
- package/dist/session/pin-tan-client.d.ts.map +1 -0
- package/dist/session/pin-tan-client.js +153 -0
- package/dist/session/pin-tan-client.js.map +1 -0
- package/dist/session/pin-tan-dialog.d.ts +71 -0
- package/dist/session/pin-tan-dialog.d.ts.map +1 -0
- package/dist/session/pin-tan-dialog.js +124 -0
- package/dist/session/pin-tan-dialog.js.map +1 -0
- package/dist/session/protocol.d.ts +209 -0
- package/dist/session/protocol.d.ts.map +1 -0
- package/dist/session/protocol.js +75 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/response-handler.d.ts +48 -0
- package/dist/session/response-handler.d.ts.map +1 -0
- package/dist/session/response-handler.js +121 -0
- package/dist/session/response-handler.js.map +1 -0
- package/dist/session/sepa-accounts.d.ts +34 -0
- package/dist/session/sepa-accounts.d.ts.map +1 -0
- package/dist/session/sepa-accounts.js +96 -0
- package/dist/session/sepa-accounts.js.map +1 -0
- package/dist/session/session-setup.d.ts +72 -0
- package/dist/session/session-setup.d.ts.map +1 -0
- package/dist/session/session-setup.js +160 -0
- package/dist/session/session-setup.js.map +1 -0
- package/dist/session/session-state.d.ts +47 -0
- package/dist/session/session-state.d.ts.map +1 -0
- package/dist/session/session-state.js +147 -0
- package/dist/session/session-state.js.map +1 -0
- package/dist/session/tan-selection.d.ts +88 -0
- package/dist/session/tan-selection.d.ts.map +1 -0
- package/dist/session/tan-selection.js +178 -0
- package/dist/session/tan-selection.js.map +1 -0
- package/dist/session/user-prompts.d.ts +61 -0
- package/dist/session/user-prompts.d.ts.map +1 -0
- package/dist/session/user-prompts.js +164 -0
- package/dist/session/user-prompts.js.map +1 -0
- package/dist/tan/challenge.d.ts +114 -0
- package/dist/tan/challenge.d.ts.map +1 -0
- package/dist/tan/challenge.js +185 -0
- package/dist/tan/challenge.js.map +1 -0
- package/dist/tan/flicker.d.ts +36 -0
- package/dist/tan/flicker.d.ts.map +1 -0
- package/dist/tan/flicker.js +262 -0
- package/dist/tan/flicker.js.map +1 -0
- package/dist/tan/tan-image.d.ts +21 -0
- package/dist/tan/tan-image.d.ts.map +1 -0
- package/dist/tan/tan-image.js +41 -0
- package/dist/tan/tan-image.js.map +1 -0
- package/dist/tan/tan-models.d.ts +145 -0
- package/dist/tan/tan-models.d.ts.map +1 -0
- package/dist/tan/tan-models.js +148 -0
- package/dist/tan/tan-models.js.map +1 -0
- package/dist/util/async.d.ts +24 -0
- package/dist/util/async.d.ts.map +1 -0
- package/dist/util/async.js +49 -0
- package/dist/util/async.js.map +1 -0
- package/dist/util/bytes.d.ts +23 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +136 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/call-context.d.ts +12 -0
- package/dist/util/call-context.d.ts.map +1 -0
- package/dist/util/call-context.js +29 -0
- package/dist/util/call-context.js.map +1 -0
- package/dist/util/dates.d.ts +62 -0
- package/dist/util/dates.d.ts.map +1 -0
- package/dist/util/dates.js +169 -0
- package/dist/util/dates.js.map +1 -0
- package/dist/util/errors.d.ts +9 -0
- package/dist/util/errors.d.ts.map +1 -0
- package/dist/util/errors.js +15 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/immutable-map.d.ts +16 -0
- package/dist/util/immutable-map.d.ts.map +1 -0
- package/dist/util/immutable-map.js +38 -0
- package/dist/util/immutable-map.js.map +1 -0
- package/dist/util/json.d.ts +13 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +44 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/text.d.ts +20 -0
- package/dist/util/text.d.ts.map +1 -0
- package/dist/util/text.js +78 -0
- package/dist/util/text.js.map +1 -0
- package/dist/util/xml.d.ts +35 -0
- package/dist/util/xml.d.ts.map +1 -0
- package/dist/util/xml.js +183 -0
- package/dist/util/xml.js.map +1 -0
- package/dist/v3/account-extension.d.ts +25 -0
- package/dist/v3/account-extension.d.ts.map +1 -0
- package/dist/v3/account-extension.js +176 -0
- package/dist/v3/account-extension.js.map +1 -0
- package/dist/v3/client.d.ts +24 -0
- package/dist/v3/client.d.ts.map +1 -0
- package/dist/v3/client.js +16 -0
- package/dist/v3/client.js.map +1 -0
- package/dist/v3/dialog.d.ts +78 -0
- package/dist/v3/dialog.d.ts.map +1 -0
- package/dist/v3/dialog.js +138 -0
- package/dist/v3/dialog.js.map +1 -0
- package/dist/v3/message.d.ts +72 -0
- package/dist/v3/message.d.ts.map +1 -0
- package/dist/v3/message.js +259 -0
- package/dist/v3/message.js.map +1 -0
- package/dist/v3/parameters.d.ts +79 -0
- package/dist/v3/parameters.d.ts.map +1 -0
- package/dist/v3/parameters.js +396 -0
- package/dist/v3/parameters.js.map +1 -0
- package/dist/v3/protocol.d.ts +68 -0
- package/dist/v3/protocol.d.ts.map +1 -0
- package/dist/v3/protocol.js +263 -0
- package/dist/v3/protocol.js.map +1 -0
- package/dist/v3/segments.d.ts +89 -0
- package/dist/v3/segments.d.ts.map +1 -0
- package/dist/v3/segments.js +283 -0
- package/dist/v3/segments.js.map +1 -0
- package/dist/v3/syntax.d.ts +76 -0
- package/dist/v3/syntax.d.ts.map +1 -0
- package/dist/v3/syntax.js +301 -0
- package/dist/v3/syntax.js.map +1 -0
- package/package.json +63 -4
- package/src/core/account.ts +250 -0
- package/src/core/amount.ts +209 -0
- package/src/core/balance.ts +84 -0
- package/src/core/bank-info.ts +66 -0
- package/src/core/client.ts +149 -0
- package/src/core/config.ts +141 -0
- package/src/core/errors.ts +203 -0
- package/src/core/feedback.ts +137 -0
- package/src/core/transaction.ts +156 -0
- package/src/core/transport.ts +114 -0
- package/src/formats/camt.ts +169 -0
- package/src/formats/mt940.ts +333 -0
- package/src/formats/readers.ts +56 -0
- package/src/formats/sepa-purpose.ts +75 -0
- package/src/index.ts +68 -0
- package/src/session/app-approval.ts +265 -0
- package/src/session/bank-connection.ts +51 -0
- package/src/session/dialog-runner.ts +119 -0
- package/src/session/login-guard.ts +135 -0
- package/src/session/parameter-data.ts +137 -0
- package/src/session/pin-tan-client.ts +186 -0
- package/src/session/pin-tan-dialog.ts +160 -0
- package/src/session/protocol.ts +311 -0
- package/src/session/response-handler.ts +130 -0
- package/src/session/sepa-accounts.ts +97 -0
- package/src/session/session-setup.ts +165 -0
- package/src/session/session-state.ts +170 -0
- package/src/session/tan-selection.ts +192 -0
- package/src/session/user-prompts.ts +174 -0
- package/src/tan/challenge.ts +252 -0
- package/src/tan/flicker.ts +270 -0
- package/src/tan/tan-image.ts +36 -0
- package/src/tan/tan-models.ts +247 -0
- package/src/util/async.ts +53 -0
- package/src/util/bytes.ts +135 -0
- package/src/util/call-context.ts +40 -0
- package/src/util/dates.ts +193 -0
- package/src/util/errors.ts +16 -0
- package/src/util/immutable-map.ts +47 -0
- package/src/util/json.ts +51 -0
- package/src/util/text.ts +82 -0
- package/src/util/xml.ts +172 -0
- package/src/v3/account-extension.ts +190 -0
- package/src/v3/client.ts +29 -0
- package/src/v3/dialog.ts +199 -0
- package/src/v3/message.ts +321 -0
- package/src/v3/parameters.ts +451 -0
- package/src/v3/protocol.ts +331 -0
- package/src/v3/segments.ts +331 -0
- package/src/v3/syntax.ts +307 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Amount } from './amount.js';
|
|
2
|
+
/** Whether a transaction is booked or still pending. */
|
|
3
|
+
export type TransactionStatus = 'booked' | 'pending';
|
|
4
|
+
/** Transaction format to request; `auto` prefers camt.052 when the bank supports it. */
|
|
5
|
+
export type TransactionFormat =
|
|
6
|
+
/** camt.052 where the bank offers it, otherwise MT940. */
|
|
7
|
+
'auto'
|
|
8
|
+
/** SWIFT MT940 (booked) and MT942 (pending). */
|
|
9
|
+
| 'mt940'
|
|
10
|
+
/** ISO 20022 camt.052. */
|
|
11
|
+
| 'camt';
|
|
12
|
+
/** What `Transaction` takes; the parsers fill in what the bank states. */
|
|
13
|
+
export interface TransactionInit {
|
|
14
|
+
status?: TransactionStatus;
|
|
15
|
+
bookingDate?: Date | undefined;
|
|
16
|
+
valueDate: Date;
|
|
17
|
+
amount: Amount;
|
|
18
|
+
isReversal?: boolean;
|
|
19
|
+
bookingText?: string | undefined;
|
|
20
|
+
purpose?: string | undefined;
|
|
21
|
+
counterpartyName?: string | undefined;
|
|
22
|
+
counterpartyIban?: string | undefined;
|
|
23
|
+
counterpartyBic?: string | undefined;
|
|
24
|
+
counterpartyAccountNumber?: string | undefined;
|
|
25
|
+
counterpartyBankCode?: string | undefined;
|
|
26
|
+
endToEndId?: string | undefined;
|
|
27
|
+
mandateId?: string | undefined;
|
|
28
|
+
creditorId?: string | undefined;
|
|
29
|
+
customerReference?: string | undefined;
|
|
30
|
+
bankReference?: string | undefined;
|
|
31
|
+
transactionCode?: string | undefined;
|
|
32
|
+
transactionTypeId?: string | undefined;
|
|
33
|
+
primaNota?: string | undefined;
|
|
34
|
+
ultimateCreditor?: string | undefined;
|
|
35
|
+
ultimateDebtor?: string | undefined;
|
|
36
|
+
purposeCodes?: ReadonlyMap<string, string>;
|
|
37
|
+
}
|
|
38
|
+
/** A single account transaction, parsed from camt.052 or MT940/MT942. */
|
|
39
|
+
export declare class Transaction {
|
|
40
|
+
/** Whether the transaction is booked or pending. */
|
|
41
|
+
readonly status: TransactionStatus;
|
|
42
|
+
/**
|
|
43
|
+
* Booking date; `undefined` where the bank states none, as for some pending transactions and MT940 entries without an
|
|
44
|
+
* entry date. A local `Date` at midnight, like every calendar date.
|
|
45
|
+
*/
|
|
46
|
+
readonly bookingDate: Date | undefined;
|
|
47
|
+
/** Value date (Valuta); for a camt entry that states its booking date only, the booking date. */
|
|
48
|
+
readonly valueDate: Date;
|
|
49
|
+
/** Signed amount; negative for debits. */
|
|
50
|
+
readonly amount: Amount;
|
|
51
|
+
/** Whether this is a reversal (Storno) of an earlier booking. */
|
|
52
|
+
readonly isReversal: boolean;
|
|
53
|
+
/** Booking type text, for example `SEPA-UEBERWEISUNG`. */
|
|
54
|
+
readonly bookingText: string | undefined;
|
|
55
|
+
/** Remittance information; the `SVWZ+` part when the bank sends SEPA keywords. */
|
|
56
|
+
readonly purpose: string | undefined;
|
|
57
|
+
/** Payee for debits, payer for credits; for a reversal, the counterparty of the booking it reverses. */
|
|
58
|
+
readonly counterpartyName: string | undefined;
|
|
59
|
+
/** IBAN of the counterparty. */
|
|
60
|
+
readonly counterpartyIban: string | undefined;
|
|
61
|
+
/** BIC of the counterparty's bank. */
|
|
62
|
+
readonly counterpartyBic: string | undefined;
|
|
63
|
+
/** National account number of the counterparty, where the bank does not state an IBAN. */
|
|
64
|
+
readonly counterpartyAccountNumber: string | undefined;
|
|
65
|
+
/** German bank code of the counterparty's bank, where the bank does not state a BIC. */
|
|
66
|
+
readonly counterpartyBankCode: string | undefined;
|
|
67
|
+
/** SEPA end-to-end reference (EREF). */
|
|
68
|
+
readonly endToEndId: string | undefined;
|
|
69
|
+
/** SEPA direct debit mandate reference (MREF). */
|
|
70
|
+
readonly mandateId: string | undefined;
|
|
71
|
+
/** SEPA creditor identifier (CRED). */
|
|
72
|
+
readonly creditorId: string | undefined;
|
|
73
|
+
/** Reference the customer gave the order. */
|
|
74
|
+
readonly customerReference: string | undefined;
|
|
75
|
+
/** Reference the bank gave the booking. */
|
|
76
|
+
readonly bankReference: string | undefined;
|
|
77
|
+
/** German business transaction code (Geschäftsvorfallcode, GVC). */
|
|
78
|
+
readonly transactionCode: string | undefined;
|
|
79
|
+
/** SWIFT transaction type, for example `NTRF`. */
|
|
80
|
+
readonly transactionTypeId: string | undefined;
|
|
81
|
+
/** Prima nota number of the booking. */
|
|
82
|
+
readonly primaNota: string | undefined;
|
|
83
|
+
/** The party the payee acts for, where that is not the payee itself. */
|
|
84
|
+
readonly ultimateCreditor: string | undefined;
|
|
85
|
+
/** The party the payer acts for, where that is not the payer itself. */
|
|
86
|
+
readonly ultimateDebtor: string | undefined;
|
|
87
|
+
/** All SEPA keywords found in the purpose, keyed by keyword (EREF, KREF, MREF, CRED, SVWZ, …). */
|
|
88
|
+
readonly purposeCodes: ReadonlyMap<string, string>;
|
|
89
|
+
constructor(init: TransactionInit);
|
|
90
|
+
/** Whether the transaction is still pending. */
|
|
91
|
+
get isPending(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* The date and status only, without amount, counterparty or purpose, so that logs and crash reports do not collect
|
|
94
|
+
* account data.
|
|
95
|
+
*/
|
|
96
|
+
toString(): string;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/core/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { formatIsoDate } from '../util/dates.js';
|
|
2
|
+
import { ImmutableMap } from '../util/immutable-map.js';
|
|
3
|
+
/** A single account transaction, parsed from camt.052 or MT940/MT942. */
|
|
4
|
+
export class Transaction {
|
|
5
|
+
/** Whether the transaction is booked or pending. */
|
|
6
|
+
status;
|
|
7
|
+
/**
|
|
8
|
+
* Booking date; `undefined` where the bank states none, as for some pending transactions and MT940 entries without an
|
|
9
|
+
* entry date. A local `Date` at midnight, like every calendar date.
|
|
10
|
+
*/
|
|
11
|
+
bookingDate;
|
|
12
|
+
/** Value date (Valuta); for a camt entry that states its booking date only, the booking date. */
|
|
13
|
+
valueDate;
|
|
14
|
+
/** Signed amount; negative for debits. */
|
|
15
|
+
amount;
|
|
16
|
+
/** Whether this is a reversal (Storno) of an earlier booking. */
|
|
17
|
+
isReversal;
|
|
18
|
+
/** Booking type text, for example `SEPA-UEBERWEISUNG`. */
|
|
19
|
+
bookingText;
|
|
20
|
+
/** Remittance information; the `SVWZ+` part when the bank sends SEPA keywords. */
|
|
21
|
+
purpose;
|
|
22
|
+
/** Payee for debits, payer for credits; for a reversal, the counterparty of the booking it reverses. */
|
|
23
|
+
counterpartyName;
|
|
24
|
+
/** IBAN of the counterparty. */
|
|
25
|
+
counterpartyIban;
|
|
26
|
+
/** BIC of the counterparty's bank. */
|
|
27
|
+
counterpartyBic;
|
|
28
|
+
/** National account number of the counterparty, where the bank does not state an IBAN. */
|
|
29
|
+
counterpartyAccountNumber;
|
|
30
|
+
/** German bank code of the counterparty's bank, where the bank does not state a BIC. */
|
|
31
|
+
counterpartyBankCode;
|
|
32
|
+
/** SEPA end-to-end reference (EREF). */
|
|
33
|
+
endToEndId;
|
|
34
|
+
/** SEPA direct debit mandate reference (MREF). */
|
|
35
|
+
mandateId;
|
|
36
|
+
/** SEPA creditor identifier (CRED). */
|
|
37
|
+
creditorId;
|
|
38
|
+
/** Reference the customer gave the order. */
|
|
39
|
+
customerReference;
|
|
40
|
+
/** Reference the bank gave the booking. */
|
|
41
|
+
bankReference;
|
|
42
|
+
/** German business transaction code (Geschäftsvorfallcode, GVC). */
|
|
43
|
+
transactionCode;
|
|
44
|
+
/** SWIFT transaction type, for example `NTRF`. */
|
|
45
|
+
transactionTypeId;
|
|
46
|
+
/** Prima nota number of the booking. */
|
|
47
|
+
primaNota;
|
|
48
|
+
/** The party the payee acts for, where that is not the payee itself. */
|
|
49
|
+
ultimateCreditor;
|
|
50
|
+
/** The party the payer acts for, where that is not the payer itself. */
|
|
51
|
+
ultimateDebtor;
|
|
52
|
+
/** All SEPA keywords found in the purpose, keyed by keyword (EREF, KREF, MREF, CRED, SVWZ, …). */
|
|
53
|
+
purposeCodes;
|
|
54
|
+
constructor(init) {
|
|
55
|
+
this.status = init.status ?? 'booked';
|
|
56
|
+
this.bookingDate = init.bookingDate;
|
|
57
|
+
this.valueDate = init.valueDate;
|
|
58
|
+
this.amount = init.amount;
|
|
59
|
+
this.isReversal = init.isReversal ?? false;
|
|
60
|
+
this.bookingText = init.bookingText;
|
|
61
|
+
this.purpose = init.purpose;
|
|
62
|
+
this.counterpartyName = init.counterpartyName;
|
|
63
|
+
this.counterpartyIban = init.counterpartyIban;
|
|
64
|
+
this.counterpartyBic = init.counterpartyBic;
|
|
65
|
+
this.counterpartyAccountNumber = init.counterpartyAccountNumber;
|
|
66
|
+
this.counterpartyBankCode = init.counterpartyBankCode;
|
|
67
|
+
this.endToEndId = init.endToEndId;
|
|
68
|
+
this.mandateId = init.mandateId;
|
|
69
|
+
this.creditorId = init.creditorId;
|
|
70
|
+
this.customerReference = init.customerReference;
|
|
71
|
+
this.bankReference = init.bankReference;
|
|
72
|
+
this.transactionCode = init.transactionCode;
|
|
73
|
+
this.transactionTypeId = init.transactionTypeId;
|
|
74
|
+
this.primaNota = init.primaNota;
|
|
75
|
+
this.ultimateCreditor = init.ultimateCreditor;
|
|
76
|
+
this.ultimateDebtor = init.ultimateDebtor;
|
|
77
|
+
this.purposeCodes = new ImmutableMap(init.purposeCodes ?? []);
|
|
78
|
+
}
|
|
79
|
+
/** Whether the transaction is still pending. */
|
|
80
|
+
get isPending() {
|
|
81
|
+
return this.status === 'pending';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The date and status only, without amount, counterparty or purpose, so that logs and crash reports do not collect
|
|
85
|
+
* account data.
|
|
86
|
+
*/
|
|
87
|
+
toString() {
|
|
88
|
+
return `Transaction(${formatIsoDate(this.bookingDate ?? this.valueDate)}, ${this.status}${this.isReversal ? ', reversal' : ''})`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/core/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Sends one FinTS message and returns the bank's reply; replace it for a relay, proxies, pinning or tests. */
|
|
2
|
+
export interface FinTsTransport {
|
|
3
|
+
/**
|
|
4
|
+
* Posts `body` to `url` and returns the response body.
|
|
5
|
+
*
|
|
6
|
+
* Implementations report failures as `FinTsTransportError`.
|
|
7
|
+
*/
|
|
8
|
+
post(url: URL, body: Uint8Array, contentType: string): Promise<Uint8Array>;
|
|
9
|
+
/** Releases the connection; the client calls it when it is closed. */
|
|
10
|
+
close(): void;
|
|
11
|
+
}
|
|
12
|
+
/** What `HttpTransport` takes; all optional. */
|
|
13
|
+
export interface HttpTransportOptions {
|
|
14
|
+
/** The `fetch` to send with, for example one with a proxy agent; the global `fetch` by default. */
|
|
15
|
+
fetch?: typeof fetch;
|
|
16
|
+
/** Time for the whole exchange in milliseconds, from sending the request to the last byte of the response; 90 s. */
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
/** Largest response accepted, so that a faulty server cannot exhaust the memory; 16 MiB. */
|
|
19
|
+
maxResponseBytes?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default `FinTsTransport`: HTTP POST with `fetch`.
|
|
23
|
+
*
|
|
24
|
+
* In a browser it only reaches servers that allow the page's origin (CORS), which bank servers do not: a web app needs
|
|
25
|
+
* a server of its own between browser and bank, reached with a `FinTsTransport` of its own.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HttpTransport implements FinTsTransport {
|
|
28
|
+
readonly timeoutMs: number;
|
|
29
|
+
readonly maxResponseBytes: number;
|
|
30
|
+
private readonly fetchFn;
|
|
31
|
+
constructor(options?: HttpTransportOptions);
|
|
32
|
+
post(url: URL, body: Uint8Array, contentType: string): Promise<Uint8Array>;
|
|
33
|
+
private exchange;
|
|
34
|
+
private readBody;
|
|
35
|
+
close(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/core/transport.ts"],"names":[],"mappings":"AAGA,+GAA+G;AAC/G,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE3E,sEAAsE;IACtE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,mGAAmG;IACnG,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,oHAAoH;IACpH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAE3B,OAAO,GAAE,oBAAyB;IAMxC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAqBlE,QAAQ;YAqBR,QAAQ;IAkBtB,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { concatBytes } from '../util/bytes.js';
|
|
2
|
+
import { FinTsTransportError } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Default `FinTsTransport`: HTTP POST with `fetch`.
|
|
5
|
+
*
|
|
6
|
+
* In a browser it only reaches servers that allow the page's origin (CORS), which bank servers do not: a web app needs
|
|
7
|
+
* a server of its own between browser and bank, reached with a `FinTsTransport` of its own.
|
|
8
|
+
*/
|
|
9
|
+
export class HttpTransport {
|
|
10
|
+
timeoutMs;
|
|
11
|
+
maxResponseBytes;
|
|
12
|
+
fetchFn;
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.fetchFn = options.fetch ?? ((input, init) => fetch(input, init));
|
|
15
|
+
this.timeoutMs = options.timeoutMs ?? 90_000;
|
|
16
|
+
this.maxResponseBytes = options.maxResponseBytes ?? 16 << 20;
|
|
17
|
+
}
|
|
18
|
+
async post(url, body, contentType) {
|
|
19
|
+
const controller = new AbortController();
|
|
20
|
+
let timer;
|
|
21
|
+
// Waiting for the timeout as well covers a `fetch` that cannot abort a request.
|
|
22
|
+
const timedOut = new Promise((_, reject) => {
|
|
23
|
+
timer = setTimeout(() => {
|
|
24
|
+
controller.abort();
|
|
25
|
+
reject(new FinTsTransportError('Request timed out'));
|
|
26
|
+
}, this.timeoutMs);
|
|
27
|
+
});
|
|
28
|
+
try {
|
|
29
|
+
return await Promise.race([this.exchange(url, body, contentType, controller.signal), timedOut]);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error instanceof FinTsTransportError)
|
|
33
|
+
throw error;
|
|
34
|
+
if (controller.signal.aborted)
|
|
35
|
+
throw new FinTsTransportError('Request timed out');
|
|
36
|
+
throw new FinTsTransportError(describe(error));
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async exchange(url, body, contentType, signal) {
|
|
43
|
+
const response = await this.fetchFn(url, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
body: body,
|
|
46
|
+
headers: { 'Content-Type': contentType, 'Cache-Control': 'no-cache', Pragma: 'no-cache' },
|
|
47
|
+
// The PIN travels in the body: never let the request be repeated at another address.
|
|
48
|
+
redirect: 'manual',
|
|
49
|
+
signal,
|
|
50
|
+
});
|
|
51
|
+
if (response.type === 'opaqueredirect') {
|
|
52
|
+
throw new FinTsTransportError('The server redirects the request, which the client does not follow');
|
|
53
|
+
}
|
|
54
|
+
if (response.status < 200 || response.status > 299) {
|
|
55
|
+
await response.body?.cancel().catch(() => undefined);
|
|
56
|
+
throw new FinTsTransportError(`HTTP ${response.status} ${response.statusText}`.trim(), {
|
|
57
|
+
statusCode: response.status,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return this.readBody(response);
|
|
61
|
+
}
|
|
62
|
+
async readBody(response) {
|
|
63
|
+
const reader = response.body?.getReader();
|
|
64
|
+
if (reader === undefined)
|
|
65
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
66
|
+
const chunks = [];
|
|
67
|
+
let size = 0;
|
|
68
|
+
for (;;) {
|
|
69
|
+
const { done, value } = await reader.read();
|
|
70
|
+
if (done)
|
|
71
|
+
break;
|
|
72
|
+
chunks.push(value);
|
|
73
|
+
size += value.length;
|
|
74
|
+
if (size > this.maxResponseBytes) {
|
|
75
|
+
await reader.cancel().catch(() => undefined);
|
|
76
|
+
throw new FinTsTransportError(`Response larger than ${this.maxResponseBytes} bytes`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return concatBytes(chunks);
|
|
80
|
+
}
|
|
81
|
+
close() {
|
|
82
|
+
// `fetch` keeps no connection the transport could release.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** The message of a `fetch` failure, with its cause: Node.js reports `fetch failed` and the reason in the cause. */
|
|
86
|
+
function describe(error) {
|
|
87
|
+
if (!(error instanceof Error))
|
|
88
|
+
return String(error);
|
|
89
|
+
const cause = error.cause;
|
|
90
|
+
return cause instanceof Error ? `${error.message}: ${cause.message}` : error.message;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/core/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Transaction, type TransactionStatus } from '../core/transaction.js';
|
|
2
|
+
/** Parser for ISO 20022 camt.052 and camt.053 account reports. */
|
|
3
|
+
export declare const Camt: Readonly<{
|
|
4
|
+
/**
|
|
5
|
+
* Parses all entries; throws `FormatError` for malformed XML, and for an entry without amount, currency, credit/debit
|
|
6
|
+
* indicator or date.
|
|
7
|
+
*
|
|
8
|
+
* `status` overrides the booking status stated in the entries.
|
|
9
|
+
*/
|
|
10
|
+
parseTransactions(xml: string, status?: TransactionStatus): Transaction[];
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=camt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camt.d.ts","sourceRoot":"","sources":["../../src/formats/camt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAM7E,kEAAkE;AAClE,eAAO,MAAM,IAAI;IACf;;;;;OAKG;2BACoB,MAAM,WAAW,iBAAiB,GAAG,WAAW,EAAE;EAIzE,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Amount } from '../core/amount.js';
|
|
2
|
+
import { Transaction } from '../core/transaction.js';
|
|
3
|
+
import { parseIsoDate } from '../util/dates.js';
|
|
4
|
+
import { FormatError } from '../util/errors.js';
|
|
5
|
+
import { parseXml } from '../util/xml.js';
|
|
6
|
+
import { providedReference, SepaPurpose } from './sepa-purpose.js';
|
|
7
|
+
/** Parser for ISO 20022 camt.052 and camt.053 account reports. */
|
|
8
|
+
export const Camt = Object.freeze({
|
|
9
|
+
/**
|
|
10
|
+
* Parses all entries; throws `FormatError` for malformed XML, and for an entry without amount, currency, credit/debit
|
|
11
|
+
* indicator or date.
|
|
12
|
+
*
|
|
13
|
+
* `status` overrides the booking status stated in the entries.
|
|
14
|
+
*/
|
|
15
|
+
parseTransactions(xml, status) {
|
|
16
|
+
const root = parseXml(xml.trim());
|
|
17
|
+
return root.descendantsNamed('Ntry').flatMap((entry) => new CamtEntry(entry, status).transactions());
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
/** Width of the purpose lines banks cut the remittance information into, as in MT940 and DTAUS. */
|
|
21
|
+
const cutLineLength = 35;
|
|
22
|
+
/**
|
|
23
|
+
* One booking (`Ntry`) of a report; a batch booking yields one transaction per transaction detail (`TxDtls`) when every
|
|
24
|
+
* detail states its amount.
|
|
25
|
+
*
|
|
26
|
+
* Nothing is guessed: what the entry lacks, and what the reader needs, is a `FormatError`. The one exception is the
|
|
27
|
+
* value date, which `Transaction.valueDate` requires: an entry with a booking date only takes that.
|
|
28
|
+
*/
|
|
29
|
+
class CamtEntry {
|
|
30
|
+
entry;
|
|
31
|
+
amountElement;
|
|
32
|
+
currency;
|
|
33
|
+
debit;
|
|
34
|
+
reversal;
|
|
35
|
+
status;
|
|
36
|
+
bookingDate;
|
|
37
|
+
valueDate;
|
|
38
|
+
/** German banks send `transaction type+GVC+prima nota`, for example `NDDT+105+9310`. */
|
|
39
|
+
proprietaryCode;
|
|
40
|
+
constructor(entry, forcedStatus) {
|
|
41
|
+
this.entry = entry;
|
|
42
|
+
this.amountElement = entry.child('Amt') ?? fail('camt entry without amount');
|
|
43
|
+
this.currency = this.amountElement.getAttribute('Ccy') ?? fail('camt amount without currency');
|
|
44
|
+
this.debit = debitIndicator(entry.textAt(['CdtDbtInd'])) ?? fail('camt entry without credit/debit indicator');
|
|
45
|
+
this.reversal = ['true', '1'].includes(entry.textAt(['RvslInd']) ?? '');
|
|
46
|
+
this.status = forcedStatus ?? this.statusOfEntry();
|
|
47
|
+
this.bookingDate = dateOf(entry.child('BookgDt'));
|
|
48
|
+
this.valueDate = dateOf(entry.child('ValDt')) ?? this.bookingDate ?? fail('camt entry without date');
|
|
49
|
+
this.proprietaryCode = entry.textAt(['BkTxCd', 'Prtry', 'Cd'])?.split('+') ?? [];
|
|
50
|
+
}
|
|
51
|
+
statusOfEntry() {
|
|
52
|
+
const code = this.entry.textAt(['Sts', 'Cd']) ?? this.entry.textAt(['Sts']);
|
|
53
|
+
return code === 'PDNG' || code === 'INFO' ? 'pending' : 'booked';
|
|
54
|
+
}
|
|
55
|
+
transactions() {
|
|
56
|
+
const total = Amount.parseDecimal(this.amountElement.innerText, this.currency);
|
|
57
|
+
const details = this.entry.descendantsNamed('TxDtls');
|
|
58
|
+
if (details.length <= 1)
|
|
59
|
+
return [this.transaction(details[0], total, this.debit)];
|
|
60
|
+
const amounts = details.map((detail) => detail.at(['AmtDtls', 'TxAmt', 'Amt']) ?? detail.child('Amt'));
|
|
61
|
+
// Without the amount of every detail the batch cannot be split. It stays one booking then, without the details of
|
|
62
|
+
// any one of them, which would describe the others wrongly.
|
|
63
|
+
if (amounts.includes(undefined))
|
|
64
|
+
return [this.transaction(undefined, total, this.debit)];
|
|
65
|
+
return details.map((detail, i) => {
|
|
66
|
+
const amount = amounts[i];
|
|
67
|
+
return this.transaction(detail, Amount.parseDecimal(amount.innerText, amount.getAttribute('Ccy') ?? this.currency),
|
|
68
|
+
// A detail may book in the other direction than the batch as a whole.
|
|
69
|
+
debitIndicator(detail.textAt(['CdtDbtInd'])) ?? this.debit);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** A transaction of `amount`, booked as a debit if `debit`, with what `details` tell about it. */
|
|
73
|
+
transaction(details, amount, debit) {
|
|
74
|
+
const parties = details?.child('RltdPties');
|
|
75
|
+
const agents = details?.child('RltdAgts');
|
|
76
|
+
// The related parties describe the original operation, which a reversal books the other way round (ISO 20022
|
|
77
|
+
// `RvslInd`: with `CRDT` the original operation was a debit, with `DBIT` a credit).
|
|
78
|
+
const originalDebit = debit !== this.reversal;
|
|
79
|
+
const counterparty = originalDebit ? 'Cdtr' : 'Dbtr';
|
|
80
|
+
const lines = (details?.descendantsNamed('Ustrd') ?? [])
|
|
81
|
+
.map((line) => line.innerText.trim())
|
|
82
|
+
.filter((text) => text !== '');
|
|
83
|
+
const purposeParts = lines.map((line, i) => (i > 0 && lines[i - 1].length !== cutLineLength ? ` ${line}` : line));
|
|
84
|
+
const purpose = purposeParts.join('');
|
|
85
|
+
const keywords = SepaPurpose.parseParts(purposeParts);
|
|
86
|
+
const endToEndId = providedReference(details?.textAt(['Refs', 'EndToEndId']));
|
|
87
|
+
const mandateId = details?.textAt(['Refs', 'MndtId']);
|
|
88
|
+
const creditorId = creditorIdOf(parties);
|
|
89
|
+
const purposeCode = details?.textAt(['Purp', 'Cd']);
|
|
90
|
+
const typeId = this.proprietaryCode[0]?.length === 4 ? this.proprietaryCode[0] : undefined;
|
|
91
|
+
const purposeCodes = new Map(keywords);
|
|
92
|
+
if (endToEndId !== undefined)
|
|
93
|
+
purposeCodes.set('EREF', endToEndId);
|
|
94
|
+
if (mandateId !== undefined)
|
|
95
|
+
purposeCodes.set('MREF', mandateId);
|
|
96
|
+
if (creditorId !== undefined)
|
|
97
|
+
purposeCodes.set('CRED', creditorId);
|
|
98
|
+
if (purposeCode !== undefined)
|
|
99
|
+
purposeCodes.set('PURP', purposeCode);
|
|
100
|
+
return new Transaction({
|
|
101
|
+
status: this.status,
|
|
102
|
+
bookingDate: this.bookingDate,
|
|
103
|
+
valueDate: this.valueDate,
|
|
104
|
+
amount: debit ? amount.negate() : amount,
|
|
105
|
+
isReversal: this.reversal,
|
|
106
|
+
bookingText: this.entry.textAt(['AddtlNtryInf']) ?? details?.textAt(['AddtlTxInf']),
|
|
107
|
+
purpose: keywords.get('SVWZ') ?? (purpose === '' ? details?.textAt(['AddtlTxInf']) : purpose),
|
|
108
|
+
counterpartyName: partyName(parties?.child(counterparty)),
|
|
109
|
+
counterpartyIban: parties?.child(`${counterparty}Acct`)?.textAt(['Id', 'IBAN']),
|
|
110
|
+
counterpartyAccountNumber: parties?.child(`${counterparty}Acct`)?.textAt(['Id', 'Othr', 'Id']),
|
|
111
|
+
counterpartyBic: bicOf(agents?.child(`${counterparty}Agt`)),
|
|
112
|
+
endToEndId,
|
|
113
|
+
mandateId,
|
|
114
|
+
creditorId,
|
|
115
|
+
customerReference: details?.textAt(['Refs', 'InstrId']) ?? details?.textAt(['Refs', 'PmtInfId']),
|
|
116
|
+
bankReference: details?.textAt(['Refs', 'AcctSvcrRef']) ?? this.entry.textAt(['AcctSvcrRef']),
|
|
117
|
+
transactionCode: this.proprietaryCode[1],
|
|
118
|
+
transactionTypeId: typeId,
|
|
119
|
+
primaNota: this.proprietaryCode[2],
|
|
120
|
+
ultimateCreditor: partyName(parties?.child('UltmtCdtr')),
|
|
121
|
+
ultimateDebtor: partyName(parties?.child('UltmtDbtr')),
|
|
122
|
+
purposeCodes,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function fail(message) {
|
|
127
|
+
throw new FormatError(message);
|
|
128
|
+
}
|
|
129
|
+
/** `true` for `DBIT`, `false` for `CRDT`, `undefined` if `indicator` is missing; throws for any other value. */
|
|
130
|
+
function debitIndicator(indicator) {
|
|
131
|
+
switch (indicator) {
|
|
132
|
+
case 'DBIT':
|
|
133
|
+
return true;
|
|
134
|
+
case 'CRDT':
|
|
135
|
+
return false;
|
|
136
|
+
case undefined:
|
|
137
|
+
return undefined;
|
|
138
|
+
default:
|
|
139
|
+
throw new FormatError('camt credit/debit indicator is neither CRDT nor DBIT', indicator);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function dateOf(e) {
|
|
143
|
+
return parseIsoDate(e?.textAt(['Dt']) ?? e?.textAt(['DtTm']));
|
|
144
|
+
}
|
|
145
|
+
function partyName(party) {
|
|
146
|
+
return party?.textAt(['Nm']) ?? party?.textAt(['Pty', 'Nm']);
|
|
147
|
+
}
|
|
148
|
+
function bicOf(agent) {
|
|
149
|
+
return agent?.textAt(['FinInstnId', 'BIC']) ?? agent?.textAt(['FinInstnId', 'BICFI']);
|
|
150
|
+
}
|
|
151
|
+
/** The SEPA creditor identifier: the `Othr` identification in the scheme `SEPA`. */
|
|
152
|
+
function creditorIdOf(parties) {
|
|
153
|
+
for (const other of parties?.descendantsNamed('Othr') ?? []) {
|
|
154
|
+
if (other.textAt(['SchmeNm', 'Prtry']) === 'SEPA')
|
|
155
|
+
return other.textAt(['Id']);
|
|
156
|
+
}
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=camt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camt.js","sourceRoot":"","sources":["../../src/formats/camt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Amount } from '../core/amount.js';
|
|
2
|
+
import { Transaction, type TransactionStatus } from '../core/transaction.js';
|
|
3
|
+
/** One statement from an MT940 or MT942 file, with its balances and transactions. */
|
|
4
|
+
export interface Mt940Statement {
|
|
5
|
+
/** The sender's reference of the statement (field 20). */
|
|
6
|
+
readonly reference: string | undefined;
|
|
7
|
+
/** The account the statement is for (field 25). */
|
|
8
|
+
readonly accountId: string | undefined;
|
|
9
|
+
/** Statement and sequence number (field 28C). */
|
|
10
|
+
readonly statementNumber: string | undefined;
|
|
11
|
+
/** Currency of the statement; `undefined` for a statement without balances and transactions. */
|
|
12
|
+
readonly currency: string | undefined;
|
|
13
|
+
/** The balance at the start of the statement (field 60), negative for a debit. */
|
|
14
|
+
readonly openingBalance: Amount | undefined;
|
|
15
|
+
/** The date of `openingBalance`. */
|
|
16
|
+
readonly openingDate: Date | undefined;
|
|
17
|
+
/** The balance at the end of the statement (field 62), negative for a debit. */
|
|
18
|
+
readonly closingBalance: Amount | undefined;
|
|
19
|
+
/** The date of `closingBalance`. */
|
|
20
|
+
readonly closingDate: Date | undefined;
|
|
21
|
+
/** The transactions of the statement, in the order the bank lists them. */
|
|
22
|
+
readonly transactions: readonly Transaction[];
|
|
23
|
+
}
|
|
24
|
+
/** What the MT940 parser takes besides the text. */
|
|
25
|
+
export interface Mt940Options {
|
|
26
|
+
/** The status of the transactions: `booked` (MT940, the default) or `pending` (MT942). */
|
|
27
|
+
status?: TransactionStatus;
|
|
28
|
+
/** The currency of statements that state none in their balances. */
|
|
29
|
+
currency?: string | undefined;
|
|
30
|
+
}
|
|
31
|
+
/** Parser for SWIFT MT940/MT942 statements, including German structured `:86:` fields. */
|
|
32
|
+
export declare const Mt940: Readonly<{
|
|
33
|
+
/** Parses all transactions; see `parse`. */
|
|
34
|
+
parseTransactions(text: string, options?: Mt940Options): Transaction[];
|
|
35
|
+
/**
|
|
36
|
+
* Parses all statements.
|
|
37
|
+
*
|
|
38
|
+
* Throws `FormatError` if a transaction line (`:61:`) cannot be read or the currency of a transaction is unknown.
|
|
39
|
+
*/
|
|
40
|
+
parse(text: string, options?: Mt940Options): Mt940Statement[];
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=mt940.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mt940.d.ts","sourceRoot":"","sources":["../../src/formats/mt940.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAM7E,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,iDAAiD;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,oCAAoC;IACpC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,SAAS,CAAC;IACvC,gFAAgF;IAChF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,oCAAoC;IACpC,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,SAAS,CAAC;IACvC,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;CAC/C;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,0FAA0F;IAC1F,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAMD,0FAA0F;AAC1F,eAAO,MAAM,KAAK;IAChB,4CAA4C;4BACpB,MAAM,YAAW,YAAY,GAAQ,WAAW,EAAE;IAI1E;;;;OAIG;gBACS,MAAM,YAAW,YAAY,GAAQ,cAAc,EAAE;EAuBjE,CAAC"}
|