@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.
Files changed (254) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +28 -0
  3. package/README.md +156 -2
  4. package/dist/core/account.d.ts +140 -0
  5. package/dist/core/account.d.ts.map +1 -0
  6. package/dist/core/account.js +174 -0
  7. package/dist/core/account.js.map +1 -0
  8. package/dist/core/amount.d.ts +62 -0
  9. package/dist/core/amount.d.ts.map +1 -0
  10. package/dist/core/amount.js +189 -0
  11. package/dist/core/amount.js.map +1 -0
  12. package/dist/core/balance.d.ts +54 -0
  13. package/dist/core/balance.d.ts.map +1 -0
  14. package/dist/core/balance.js +53 -0
  15. package/dist/core/balance.js.map +1 -0
  16. package/dist/core/bank-info.d.ts +49 -0
  17. package/dist/core/bank-info.d.ts.map +1 -0
  18. package/dist/core/bank-info.js +52 -0
  19. package/dist/core/bank-info.js.map +1 -0
  20. package/dist/core/client.d.ts +126 -0
  21. package/dist/core/client.d.ts.map +1 -0
  22. package/dist/core/client.js +2 -0
  23. package/dist/core/client.js.map +1 -0
  24. package/dist/core/config.d.ts +68 -0
  25. package/dist/core/config.d.ts.map +1 -0
  26. package/dist/core/config.js +113 -0
  27. package/dist/core/config.js.map +1 -0
  28. package/dist/core/errors.d.ts +91 -0
  29. package/dist/core/errors.d.ts.map +1 -0
  30. package/dist/core/errors.js +182 -0
  31. package/dist/core/errors.js.map +1 -0
  32. package/dist/core/feedback.d.ts +69 -0
  33. package/dist/core/feedback.d.ts.map +1 -0
  34. package/dist/core/feedback.js +124 -0
  35. package/dist/core/feedback.js.map +1 -0
  36. package/dist/core/transaction.d.ts +98 -0
  37. package/dist/core/transaction.d.ts.map +1 -0
  38. package/dist/core/transaction.js +91 -0
  39. package/dist/core/transaction.js.map +1 -0
  40. package/dist/core/transport.d.ts +37 -0
  41. package/dist/core/transport.d.ts.map +1 -0
  42. package/dist/core/transport.js +92 -0
  43. package/dist/core/transport.js.map +1 -0
  44. package/dist/formats/camt.d.ts +12 -0
  45. package/dist/formats/camt.d.ts.map +1 -0
  46. package/dist/formats/camt.js +159 -0
  47. package/dist/formats/camt.js.map +1 -0
  48. package/dist/formats/mt940.d.ts +42 -0
  49. package/dist/formats/mt940.d.ts.map +1 -0
  50. package/dist/formats/mt940.js +297 -0
  51. package/dist/formats/mt940.js.map +1 -0
  52. package/dist/formats/readers.d.ts +11 -0
  53. package/dist/formats/readers.d.ts.map +1 -0
  54. package/dist/formats/readers.js +47 -0
  55. package/dist/formats/readers.js.map +1 -0
  56. package/dist/formats/sepa-purpose.d.ts +22 -0
  57. package/dist/formats/sepa-purpose.d.ts.map +1 -0
  58. package/dist/formats/sepa-purpose.js +68 -0
  59. package/dist/formats/sepa-purpose.js.map +1 -0
  60. package/dist/index.d.ts +28 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +27 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/session/app-approval.d.ts +60 -0
  65. package/dist/session/app-approval.d.ts.map +1 -0
  66. package/dist/session/app-approval.js +215 -0
  67. package/dist/session/app-approval.js.map +1 -0
  68. package/dist/session/bank-connection.d.ts +28 -0
  69. package/dist/session/bank-connection.d.ts.map +1 -0
  70. package/dist/session/bank-connection.js +48 -0
  71. package/dist/session/bank-connection.js.map +1 -0
  72. package/dist/session/dialog-runner.d.ts +34 -0
  73. package/dist/session/dialog-runner.d.ts.map +1 -0
  74. package/dist/session/dialog-runner.js +112 -0
  75. package/dist/session/dialog-runner.js.map +1 -0
  76. package/dist/session/login-guard.d.ts +73 -0
  77. package/dist/session/login-guard.d.ts.map +1 -0
  78. package/dist/session/login-guard.js +109 -0
  79. package/dist/session/login-guard.js.map +1 -0
  80. package/dist/session/parameter-data.d.ts +83 -0
  81. package/dist/session/parameter-data.d.ts.map +1 -0
  82. package/dist/session/parameter-data.js +68 -0
  83. package/dist/session/parameter-data.js.map +1 -0
  84. package/dist/session/pin-tan-client.d.ts +54 -0
  85. package/dist/session/pin-tan-client.d.ts.map +1 -0
  86. package/dist/session/pin-tan-client.js +153 -0
  87. package/dist/session/pin-tan-client.js.map +1 -0
  88. package/dist/session/pin-tan-dialog.d.ts +71 -0
  89. package/dist/session/pin-tan-dialog.d.ts.map +1 -0
  90. package/dist/session/pin-tan-dialog.js +124 -0
  91. package/dist/session/pin-tan-dialog.js.map +1 -0
  92. package/dist/session/protocol.d.ts +209 -0
  93. package/dist/session/protocol.d.ts.map +1 -0
  94. package/dist/session/protocol.js +75 -0
  95. package/dist/session/protocol.js.map +1 -0
  96. package/dist/session/response-handler.d.ts +48 -0
  97. package/dist/session/response-handler.d.ts.map +1 -0
  98. package/dist/session/response-handler.js +121 -0
  99. package/dist/session/response-handler.js.map +1 -0
  100. package/dist/session/sepa-accounts.d.ts +34 -0
  101. package/dist/session/sepa-accounts.d.ts.map +1 -0
  102. package/dist/session/sepa-accounts.js +96 -0
  103. package/dist/session/sepa-accounts.js.map +1 -0
  104. package/dist/session/session-setup.d.ts +72 -0
  105. package/dist/session/session-setup.d.ts.map +1 -0
  106. package/dist/session/session-setup.js +160 -0
  107. package/dist/session/session-setup.js.map +1 -0
  108. package/dist/session/session-state.d.ts +47 -0
  109. package/dist/session/session-state.d.ts.map +1 -0
  110. package/dist/session/session-state.js +147 -0
  111. package/dist/session/session-state.js.map +1 -0
  112. package/dist/session/tan-selection.d.ts +88 -0
  113. package/dist/session/tan-selection.d.ts.map +1 -0
  114. package/dist/session/tan-selection.js +178 -0
  115. package/dist/session/tan-selection.js.map +1 -0
  116. package/dist/session/user-prompts.d.ts +61 -0
  117. package/dist/session/user-prompts.d.ts.map +1 -0
  118. package/dist/session/user-prompts.js +164 -0
  119. package/dist/session/user-prompts.js.map +1 -0
  120. package/dist/tan/challenge.d.ts +114 -0
  121. package/dist/tan/challenge.d.ts.map +1 -0
  122. package/dist/tan/challenge.js +185 -0
  123. package/dist/tan/challenge.js.map +1 -0
  124. package/dist/tan/flicker.d.ts +36 -0
  125. package/dist/tan/flicker.d.ts.map +1 -0
  126. package/dist/tan/flicker.js +262 -0
  127. package/dist/tan/flicker.js.map +1 -0
  128. package/dist/tan/tan-image.d.ts +21 -0
  129. package/dist/tan/tan-image.d.ts.map +1 -0
  130. package/dist/tan/tan-image.js +41 -0
  131. package/dist/tan/tan-image.js.map +1 -0
  132. package/dist/tan/tan-models.d.ts +145 -0
  133. package/dist/tan/tan-models.d.ts.map +1 -0
  134. package/dist/tan/tan-models.js +148 -0
  135. package/dist/tan/tan-models.js.map +1 -0
  136. package/dist/util/async.d.ts +24 -0
  137. package/dist/util/async.d.ts.map +1 -0
  138. package/dist/util/async.js +49 -0
  139. package/dist/util/async.js.map +1 -0
  140. package/dist/util/bytes.d.ts +23 -0
  141. package/dist/util/bytes.d.ts.map +1 -0
  142. package/dist/util/bytes.js +136 -0
  143. package/dist/util/bytes.js.map +1 -0
  144. package/dist/util/call-context.d.ts +12 -0
  145. package/dist/util/call-context.d.ts.map +1 -0
  146. package/dist/util/call-context.js +29 -0
  147. package/dist/util/call-context.js.map +1 -0
  148. package/dist/util/dates.d.ts +62 -0
  149. package/dist/util/dates.d.ts.map +1 -0
  150. package/dist/util/dates.js +169 -0
  151. package/dist/util/dates.js.map +1 -0
  152. package/dist/util/errors.d.ts +9 -0
  153. package/dist/util/errors.d.ts.map +1 -0
  154. package/dist/util/errors.js +15 -0
  155. package/dist/util/errors.js.map +1 -0
  156. package/dist/util/immutable-map.d.ts +16 -0
  157. package/dist/util/immutable-map.d.ts.map +1 -0
  158. package/dist/util/immutable-map.js +38 -0
  159. package/dist/util/immutable-map.js.map +1 -0
  160. package/dist/util/json.d.ts +13 -0
  161. package/dist/util/json.d.ts.map +1 -0
  162. package/dist/util/json.js +44 -0
  163. package/dist/util/json.js.map +1 -0
  164. package/dist/util/text.d.ts +20 -0
  165. package/dist/util/text.d.ts.map +1 -0
  166. package/dist/util/text.js +78 -0
  167. package/dist/util/text.js.map +1 -0
  168. package/dist/util/xml.d.ts +35 -0
  169. package/dist/util/xml.d.ts.map +1 -0
  170. package/dist/util/xml.js +183 -0
  171. package/dist/util/xml.js.map +1 -0
  172. package/dist/v3/account-extension.d.ts +25 -0
  173. package/dist/v3/account-extension.d.ts.map +1 -0
  174. package/dist/v3/account-extension.js +176 -0
  175. package/dist/v3/account-extension.js.map +1 -0
  176. package/dist/v3/client.d.ts +24 -0
  177. package/dist/v3/client.d.ts.map +1 -0
  178. package/dist/v3/client.js +16 -0
  179. package/dist/v3/client.js.map +1 -0
  180. package/dist/v3/dialog.d.ts +78 -0
  181. package/dist/v3/dialog.d.ts.map +1 -0
  182. package/dist/v3/dialog.js +138 -0
  183. package/dist/v3/dialog.js.map +1 -0
  184. package/dist/v3/message.d.ts +72 -0
  185. package/dist/v3/message.d.ts.map +1 -0
  186. package/dist/v3/message.js +259 -0
  187. package/dist/v3/message.js.map +1 -0
  188. package/dist/v3/parameters.d.ts +79 -0
  189. package/dist/v3/parameters.d.ts.map +1 -0
  190. package/dist/v3/parameters.js +396 -0
  191. package/dist/v3/parameters.js.map +1 -0
  192. package/dist/v3/protocol.d.ts +68 -0
  193. package/dist/v3/protocol.d.ts.map +1 -0
  194. package/dist/v3/protocol.js +263 -0
  195. package/dist/v3/protocol.js.map +1 -0
  196. package/dist/v3/segments.d.ts +89 -0
  197. package/dist/v3/segments.d.ts.map +1 -0
  198. package/dist/v3/segments.js +283 -0
  199. package/dist/v3/segments.js.map +1 -0
  200. package/dist/v3/syntax.d.ts +76 -0
  201. package/dist/v3/syntax.d.ts.map +1 -0
  202. package/dist/v3/syntax.js +301 -0
  203. package/dist/v3/syntax.js.map +1 -0
  204. package/package.json +63 -4
  205. package/src/core/account.ts +250 -0
  206. package/src/core/amount.ts +209 -0
  207. package/src/core/balance.ts +84 -0
  208. package/src/core/bank-info.ts +66 -0
  209. package/src/core/client.ts +149 -0
  210. package/src/core/config.ts +141 -0
  211. package/src/core/errors.ts +203 -0
  212. package/src/core/feedback.ts +137 -0
  213. package/src/core/transaction.ts +156 -0
  214. package/src/core/transport.ts +114 -0
  215. package/src/formats/camt.ts +169 -0
  216. package/src/formats/mt940.ts +333 -0
  217. package/src/formats/readers.ts +56 -0
  218. package/src/formats/sepa-purpose.ts +75 -0
  219. package/src/index.ts +68 -0
  220. package/src/session/app-approval.ts +265 -0
  221. package/src/session/bank-connection.ts +51 -0
  222. package/src/session/dialog-runner.ts +119 -0
  223. package/src/session/login-guard.ts +135 -0
  224. package/src/session/parameter-data.ts +137 -0
  225. package/src/session/pin-tan-client.ts +186 -0
  226. package/src/session/pin-tan-dialog.ts +160 -0
  227. package/src/session/protocol.ts +311 -0
  228. package/src/session/response-handler.ts +130 -0
  229. package/src/session/sepa-accounts.ts +97 -0
  230. package/src/session/session-setup.ts +165 -0
  231. package/src/session/session-state.ts +170 -0
  232. package/src/session/tan-selection.ts +192 -0
  233. package/src/session/user-prompts.ts +174 -0
  234. package/src/tan/challenge.ts +252 -0
  235. package/src/tan/flicker.ts +270 -0
  236. package/src/tan/tan-image.ts +36 -0
  237. package/src/tan/tan-models.ts +247 -0
  238. package/src/util/async.ts +53 -0
  239. package/src/util/bytes.ts +135 -0
  240. package/src/util/call-context.ts +40 -0
  241. package/src/util/dates.ts +193 -0
  242. package/src/util/errors.ts +16 -0
  243. package/src/util/immutable-map.ts +47 -0
  244. package/src/util/json.ts +51 -0
  245. package/src/util/text.ts +82 -0
  246. package/src/util/xml.ts +172 -0
  247. package/src/v3/account-extension.ts +190 -0
  248. package/src/v3/client.ts +29 -0
  249. package/src/v3/dialog.ts +199 -0
  250. package/src/v3/message.ts +321 -0
  251. package/src/v3/parameters.ts +451 -0
  252. package/src/v3/protocol.ts +331 -0
  253. package/src/v3/segments.ts +331 -0
  254. package/src/v3/syntax.ts +307 -0
@@ -0,0 +1,124 @@
1
+ import { FinTsError, FinTsProtocolError, FinTsTransportError, parseBankData } from '../core/errors.js';
2
+ import { endsDialog, FeedbackCodes, hasCode, hasErrors } from '../core/feedback.js';
3
+ import { challengeText, TanChallenge } from '../tan/challenge.js';
4
+ /**
5
+ * How long a dialog may stay idle where the bank states no timeout: on the safe side, since a dialog given up too early
6
+ * only costs a new login, while one kept too long fails the next call.
7
+ */
8
+ const defaultIdleLimitMs = 5 * 60_000;
9
+ /** The dialog logic of PIN/TAN: the TAN method and medium, the message count, the dialog's end, and the approvals. */
10
+ export class PinTanDialog {
11
+ method;
12
+ tanMedium;
13
+ messageNumber = 1;
14
+ ended = false;
15
+ /** When the bank last answered without rejecting the whole message, which shows it still knows the dialog. */
16
+ lastAnswer;
17
+ constructor(method,
18
+ /** The TAN medium the messages name, where the method takes one. */
19
+ tanMedium) {
20
+ this.method = method;
21
+ this.tanMedium = tanMedium;
22
+ }
23
+ /**
24
+ * Whether the dialog has ended, on either side.
25
+ *
26
+ * The bank ends a dialog idle for longer than its maximum timeout (HIBPA, Formals C.9), or five minutes where it
27
+ * states none. Such a dialog is neither used nor ended again: the bank would refuse any message in it.
28
+ */
29
+ get hasEnded() {
30
+ return this.ended || this.idleTooLong;
31
+ }
32
+ get idleTooLong() {
33
+ const last = this.lastAnswer;
34
+ const timeout = this.bankParameters?.bankInfo.maxTimeout;
35
+ // A timeout of 0 or below: the bank keeps idle dialogs without limit.
36
+ const limit = timeout === undefined ? defaultIdleLimitMs : timeout <= 0 ? undefined : timeout * 1000;
37
+ return last !== undefined && limit !== undefined && Date.now() - last > limit;
38
+ }
39
+ /** Whether the messages are signed with a two-step TAN method, so that the bank may ask for approvals. */
40
+ get isTwoStep() {
41
+ return !this.method.isOneStep;
42
+ }
43
+ /** The TAN medium name the messages send: the dialog's, unless the method takes none. */
44
+ get mediumName() {
45
+ return this.method.mediumRequirement === 'notAllowed' ? undefined : this.tanMedium;
46
+ }
47
+ async end() {
48
+ if (!this.isActive)
49
+ return;
50
+ this.ended = true;
51
+ try {
52
+ await this.sendEnd();
53
+ }
54
+ catch (error) {
55
+ // The bank may have ended the dialog on its side already.
56
+ if (!(error instanceof FinTsError))
57
+ throw error;
58
+ }
59
+ }
60
+ discard() {
61
+ this.ended = true;
62
+ }
63
+ /**
64
+ * Sends the next message through `post`, which takes its number, and reads the answer with `read`. The message counts
65
+ * once the bank has answered, whatever it answered.
66
+ *
67
+ * The dialog ends on the client's side, without a dialog end, where it is over for the bank: after a return code that
68
+ * ends it, such as 9800, and after a rejected opening message (Formals C.1.2), or a broken connection (C.6).
69
+ *
70
+ * Only an answer that does not reject the whole message starts the idle time anew (`hasEnded`): a rejection may come
71
+ * from a bank that has ended the dialog without saying so.
72
+ */
73
+ async transmit(post, read) {
74
+ const number = this.messageNumber;
75
+ let answer;
76
+ try {
77
+ answer = await post(number);
78
+ }
79
+ catch (error) {
80
+ if (error instanceof FinTsTransportError)
81
+ this.discard();
82
+ throw error;
83
+ }
84
+ this.messageNumber++;
85
+ const response = parseBankData(() => read(answer));
86
+ this.readDialogData(response);
87
+ if (!response.messageRejected)
88
+ this.lastAnswer = Date.now();
89
+ if (endsDialog(response.feedback) || (number === 1 && response.messageRejected))
90
+ this.discard();
91
+ return response;
92
+ }
93
+ approvalAskedIn(response) {
94
+ const feedback = response.feedback;
95
+ const asks = !hasErrors(feedback) &&
96
+ (hasCode(feedback, FeedbackCodes.tanRequired) || hasCode(feedback, FeedbackCodes.decoupledPending));
97
+ if (!asks)
98
+ return undefined;
99
+ const approval = this.approvalIn(response);
100
+ if (approval === undefined)
101
+ throw new FinTsProtocolError('The bank asks for an approval, but sends no challenge');
102
+ return approval;
103
+ }
104
+ /** The approval `response` asks for, with the challenge for the order the bank calls `reference`. */
105
+ approvalOf(response, parts) {
106
+ const feedback = response.feedback;
107
+ return {
108
+ challenge: TanChallenge.create({
109
+ method: this.method,
110
+ reference: parts.reference,
111
+ message: parts.message,
112
+ hhdUc: parts.hhdUc,
113
+ isDecoupled: hasCode(feedback, FeedbackCodes.decoupledPending) || this.method.decoupled,
114
+ validUntil: parts.validUntil,
115
+ tanMediumName: parts.tanMediumName ?? this.tanMedium,
116
+ }),
117
+ submitTan: parts.submitTan,
118
+ checkStatus: parts.checkStatus,
119
+ waitForPush: hasCode(feedback, FeedbackCodes.decoupledWaitForPush),
120
+ instructionsIn: (status) => challengeText(parts.instructionsIn(status)),
121
+ };
122
+ }
123
+ }
124
+ //# sourceMappingURL=pin-tan-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pin-tan-dialog.js","sourceRoot":"","sources":["../../src/session/pin-tan-dialog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ import type { Account } from '../core/account.js';
2
+ import type { Balance } from '../core/balance.js';
3
+ import type { BankMessage } from '../core/bank-info.js';
4
+ import { type FinTsConfig } from '../core/config.js';
5
+ import type { FinTsFeedback } from '../core/feedback.js';
6
+ import type { Transaction, TransactionFormat } from '../core/transaction.js';
7
+ import type { TanChallenge } from '../tan/challenge.js';
8
+ import type { TanMedium, TanMethod } from '../tan/tan-models.js';
9
+ import type { LoginGuard } from './login-guard.js';
10
+ import { type BankParameters, type UserParameters } from './parameter-data.js';
11
+ /**
12
+ * The filler the specification names for a reference that does not exist.
13
+ *
14
+ * The bank puts it into a dummy answer when no approval is needed. The client sends it as the TAN medium name in the
15
+ * dialog that looks up the TAN media, before it knows a medium; the bank ignores it there (PIN/TAN B.4.3.1.3).
16
+ */
17
+ export declare const noReference = "noref";
18
+ /**
19
+ * A business transaction by its name, such as `HKCAZ`, and the version to send; `undefined` where the bank does not
20
+ * offer it or the parameter data do not permit it.
21
+ */
22
+ export interface OfferedTransaction {
23
+ readonly name: string;
24
+ readonly version: number | undefined;
25
+ }
26
+ /**
27
+ * What to request for transactions: camt.052 (`camt`) or MT940, the `version` to send, the `camtFormats` to name, and
28
+ * the `currency` of statements that state none.
29
+ */
30
+ export interface TransactionsRequest {
31
+ readonly camt: boolean;
32
+ readonly version: number;
33
+ readonly camtFormats: readonly string[];
34
+ readonly currency: string | undefined;
35
+ }
36
+ /**
37
+ * What to request for the transactions of `account` in `format`.
38
+ *
39
+ * The client reads camt.052 only, so camt counts as offered only if `camtFormats` include it. With `auto` the client
40
+ * takes camt where the bank offers it, unless the user parameter data `upd` list only MT940 transactions for the
41
+ * account.
42
+ *
43
+ * Throws `FinTsUnsupportedError` if the bank does not offer the chosen format for the account.
44
+ */
45
+ export declare function chooseTransactions(format: TransactionFormat, account: Account, upd: UserParameters | undefined, offered: {
46
+ camt: OfferedTransaction;
47
+ camtFormats: readonly string[];
48
+ mt940: OfferedTransaction;
49
+ }): TransactionsRequest;
50
+ /**
51
+ * The query for the balance of `account`.
52
+ *
53
+ * `order` builds the request for each page. Once all pages are in, `records` collects the balance records of all pages,
54
+ * `balanceRecord` picks the one for `account` with the help of `accountOf`, and `read` turns it into the `Balance`.
55
+ */
56
+ export declare function balanceQuery<R extends BankResponse, O, T>(account: Account, parts: {
57
+ order: (continuation: string | undefined) => O;
58
+ records: (pages: readonly R[]) => T[];
59
+ accountOf: (record: T) => Account;
60
+ read: (record: T, account: Account) => Balance;
61
+ }): Query<R, O, Balance>;
62
+ /**
63
+ * Checks that a message signed with `pin` may go out.
64
+ *
65
+ * It may not if the bank refused a login before (`LoginGuard.check`), or if the bank parameters `bpd` rule out the
66
+ * PIN's length: the bank would count such a PIN as a failed attempt.
67
+ */
68
+ export declare function checkBeforeSigning(guard: LoginGuard, pin: string, bpd: BankParameters | undefined): void;
69
+ /**
70
+ * The balance record of `account` in `records`: the one whose account matches. A single record is taken as it is,
71
+ * since the query asked for this one account only.
72
+ *
73
+ * Throws `FinTsBankError` with the bank's `feedback` if there is none, and `FinTsProtocolError` if there are several
74
+ * and none matches.
75
+ */
76
+ export declare function balanceRecord<T>(records: readonly T[], account: Account, accountOf: (record: T) => Account, feedback: readonly FinTsFeedback[]): T;
77
+ /** A bank response, reduced to what the protocol-independent session logic needs. */
78
+ export interface BankResponse {
79
+ /** Return codes of the whole message and of its parts. */
80
+ readonly feedback: readonly FinTsFeedback[];
81
+ /** Whether the bank rejected the message as a whole (an error in HIRMG), rather than single orders in it. */
82
+ readonly messageRejected: boolean;
83
+ /** Free-text messages the bank addresses to the user. */
84
+ readonly bankMessages: readonly BankMessage[];
85
+ /** The length of the message in bytes, a measure of the memory it holds. */
86
+ readonly size: number;
87
+ }
88
+ /** The bank's request to approve a message with a TAN or in a banking app. */
89
+ export interface Approval<R> {
90
+ /** What the user is asked. */
91
+ readonly challenge: TanChallenge;
92
+ /** Sends the TAN the user entered. */
93
+ readonly submitTan: (tan: string) => Promise<R>;
94
+ /** Asks the bank whether the user has approved in the banking app. */
95
+ readonly checkStatus: () => Promise<R>;
96
+ /**
97
+ * Whether the bank announces a push message for once the user has approved (return code 3957), before which the
98
+ * status must not be asked. The client has no push channel, so the user reports the approval instead.
99
+ */
100
+ readonly waitForPush: boolean;
101
+ /** The new instructions a status answer gives the user (return code 3956); `undefined` where it gives none. */
102
+ readonly instructionsIn: (response: R) => string | undefined;
103
+ }
104
+ /** One message exchange of a dialog, sent when called. */
105
+ export type Exchange<R> = () => Promise<R>;
106
+ /**
107
+ * The messages that open a dialog and send an order: `login` opens the dialog, and `order` sends the order in a message
108
+ * of its own.
109
+ */
110
+ export interface StartWithOrder<R> {
111
+ readonly login: Exchange<R>;
112
+ readonly order: Exchange<R> | undefined;
113
+ }
114
+ /** What the handling of responses needs of a dialog, whatever its protocol. */
115
+ export interface DialogHandle<R extends BankResponse> {
116
+ /** The TAN method the dialog's messages are signed with. */
117
+ readonly method: TanMethod;
118
+ /** Whether the bank knows this dialog and it has not ended. */
119
+ readonly isActive: boolean;
120
+ /**
121
+ * The approval `response`, the dialog's latest answer, asks for with return code 0030 (TAN) or 3955 (banking app);
122
+ * `undefined` if it asks for none.
123
+ *
124
+ * The bank has not executed the message then, so a request without a challenge is a `FinTsProtocolError`: read as
125
+ * done, it would report an empty result.
126
+ */
127
+ approvalAskedIn(response: R): Approval<R> | undefined;
128
+ /** Forgets the dialog without contacting the bank, for example after the bank rejected the PIN. */
129
+ discard(): void;
130
+ /**
131
+ * Ends the dialog at the bank; does nothing if it is not active.
132
+ *
133
+ * Bank and connection errors are ignored, since the bank may have ended the dialog on its side already.
134
+ */
135
+ end(): Promise<void>;
136
+ }
137
+ /** One dialog with the bank: a numbered sequence of messages under one dialog ID. */
138
+ export interface ProtocolDialog<R extends BankResponse, O> extends DialogHandle<R> {
139
+ /** Opens the dialog; with `synchronize` the bank also assigns a customer system ID. */
140
+ start(synchronize?: boolean): Promise<R>;
141
+ /** The messages that open the dialog and send `order` while no TAN medium is chosen yet, as for listing the media. */
142
+ startWith(order: O): StartWithOrder<R>;
143
+ /** Sends `order`, asking for strong customer authentication where the bank requires it. */
144
+ send(order: O): Promise<R>;
145
+ }
146
+ /** A business transaction: the order to send for each page, and how to read all pages the bank sent. */
147
+ export interface Query<R, O, T> {
148
+ /** The order for the page at `continuation`; `undefined` for the first page. */
149
+ readonly order: (continuation: string | undefined) => O;
150
+ /** Reads the result; throws `FormatError` for malformed data. */
151
+ readonly read: (pages: readonly R[]) => T;
152
+ }
153
+ /**
154
+ * What the regular dialogs still need from a synchronization, a login in a dialog of its own, before the TAN method and
155
+ * medium are settled (`TanSelection.synchronizationDialog` tells which method signs it):
156
+ * - `none`: nothing, so no synchronization runs;
157
+ * - `helpful`: nothing they cannot get themselves, but it tells the TAN methods the user may use before the user
158
+ * chooses one, so it runs once per client;
159
+ * - `required`: the customer system ID, without which no regular dialog starts (FinTS 3.0).
160
+ */
161
+ export type Synchronization = 'none' | 'helpful' | 'required';
162
+ /** What the handling of responses needs of a protocol, whatever the orders it builds. */
163
+ export interface ResponseProtocol<R extends BankResponse> {
164
+ /** Keeps the parameter data and IDs in `response`, the answer to a message of a logged-in dialog. */
165
+ keepParameterData(response: R): void;
166
+ /** Joins a response with the one completing its approval. */
167
+ combine(first: R, second: R): R;
168
+ }
169
+ /**
170
+ * The protocol-specific half of a PIN/TAN client: builds and reads the messages.
171
+ *
172
+ * `PinTanClient` holds the other half, the session logic.
173
+ */
174
+ export interface PinTanProtocol<R extends BankResponse, O> extends ResponseProtocol<R> {
175
+ /** Where and as whom the client talks to the bank. */
176
+ readonly config: FinTsConfig;
177
+ /** The bank parameter data received so far, if any. */
178
+ readonly bankParameters: BankParameters | undefined;
179
+ /** The user parameter data received so far, if any. */
180
+ readonly userParameters: UserParameters | undefined;
181
+ /** What regular dialogs still need from a synchronization dialog. */
182
+ readonly synchronization: Synchronization;
183
+ /**
184
+ * Drops the customer system ID the bank no longer accepts, so that a synchronization is required again; returns
185
+ * whether there was one.
186
+ */
187
+ forgetSystemId(): boolean;
188
+ /** Keeps the PIN from going out after a refused login: the protocol checks it before every message it signs. */
189
+ readonly loginGuard: LoginGuard;
190
+ /** Requests the bank parameter data without logging in, and keeps them. */
191
+ fetchBankParametersAnonymously(): Promise<R>;
192
+ /** A new dialog signed with `method` and, where the method needs one, `tanMedium`. */
193
+ newDialog(method: TanMethod, tanMedium?: string): ProtocolDialog<R, O>;
194
+ /** Lists the TAN media; `undefined` if the bank does not offer it. */
195
+ tanMedia(): Query<R, O, TanMedium[]> | undefined;
196
+ /** Lists IBAN and BIC of the accounts; `undefined` if the bank does not offer it. */
197
+ sepaAccounts(): Query<R, O, Account[]> | undefined;
198
+ /** The balance of `account`; throws `FinTsUnsupportedError` if the bank does not report balances. */
199
+ balance(account: Account): Query<R, O, Balance>;
200
+ /** The transactions of `account`; throws `FinTsUnsupportedError` if the bank does not offer `format`. */
201
+ transactions(account: Account, format: TransactionFormat, from: Date | undefined, to: Date | undefined): Query<R, O, Transaction[]>;
202
+ /** The parameter data and IDs the protocol keeps, as JSON data, for the client's saved state. */
203
+ saveState(): Record<string, unknown>;
204
+ /** Restores what `saveState` saved; throws if `saved` is damaged, leaving the protocol unchanged. */
205
+ restoreState(saved: Record<string, unknown>): void;
206
+ /** Releases the connection. */
207
+ close(): void;
208
+ }
209
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/session/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import { requirePinLength } from '../core/config.js';
2
+ import { FinTsBankError, FinTsProtocolError, FinTsUnsupportedError } from '../core/errors.js';
3
+ import { knownAccount, lists } from './parameter-data.js';
4
+ /**
5
+ * The filler the specification names for a reference that does not exist.
6
+ *
7
+ * The bank puts it into a dummy answer when no approval is needed. The client sends it as the TAN medium name in the
8
+ * dialog that looks up the TAN media, before it knows a medium; the bank ignores it there (PIN/TAN B.4.3.1.3).
9
+ */
10
+ export const noReference = 'noref';
11
+ /**
12
+ * What to request for the transactions of `account` in `format`.
13
+ *
14
+ * The client reads camt.052 only, so camt counts as offered only if `camtFormats` include it. With `auto` the client
15
+ * takes camt where the bank offers it, unless the user parameter data `upd` list only MT940 transactions for the
16
+ * account.
17
+ *
18
+ * Throws `FinTsUnsupportedError` if the bank does not offer the chosen format for the account.
19
+ */
20
+ export function chooseTransactions(format, account, upd, offered) {
21
+ const readable = offered.camtFormats.filter((f) => f.includes('camt.052'));
22
+ const camtVersion = readable.length === 0 ? undefined : offered.camt.version;
23
+ const known = knownAccount(upd, account);
24
+ const useCamt = format === 'camt' ||
25
+ (format === 'auto' &&
26
+ camtVersion !== undefined &&
27
+ (lists(known, offered.camt.name) || !lists(known, offered.mt940.name)));
28
+ const version = useCamt ? camtVersion : offered.mt940.version;
29
+ if (version === undefined) {
30
+ const name = useCamt ? offered.camt.name : offered.mt940.name;
31
+ throw new FinTsUnsupportedError(`The bank offers no ${useCamt ? 'camt ' : ''}transactions (${name}) for this account`);
32
+ }
33
+ return { camt: useCamt, version, camtFormats: readable, currency: known.currency ?? account.currency };
34
+ }
35
+ /**
36
+ * The query for the balance of `account`.
37
+ *
38
+ * `order` builds the request for each page. Once all pages are in, `records` collects the balance records of all pages,
39
+ * `balanceRecord` picks the one for `account` with the help of `accountOf`, and `read` turns it into the `Balance`.
40
+ */
41
+ export function balanceQuery(account, parts) {
42
+ return {
43
+ order: parts.order,
44
+ read: (pages) => parts.read(balanceRecord(parts.records(pages), account, parts.accountOf, pages.flatMap((p) => p.feedback)), account),
45
+ };
46
+ }
47
+ /**
48
+ * Checks that a message signed with `pin` may go out.
49
+ *
50
+ * It may not if the bank refused a login before (`LoginGuard.check`), or if the bank parameters `bpd` rule out the
51
+ * PIN's length: the bank would count such a PIN as a failed attempt.
52
+ */
53
+ export function checkBeforeSigning(guard, pin, bpd) {
54
+ guard.check();
55
+ requirePinLength(pin, bpd?.pinLength.min, bpd?.pinLength.max);
56
+ }
57
+ /**
58
+ * The balance record of `account` in `records`: the one whose account matches. A single record is taken as it is,
59
+ * since the query asked for this one account only.
60
+ *
61
+ * Throws `FinTsBankError` with the bank's `feedback` if there is none, and `FinTsProtocolError` if there are several
62
+ * and none matches.
63
+ */
64
+ export function balanceRecord(records, account, accountOf, feedback) {
65
+ if (records.length === 0)
66
+ throw new FinTsBankError(feedback, 'No balance returned');
67
+ if (records.length === 1)
68
+ return records[0];
69
+ const match = records.find((record) => accountOf(record).matches(account));
70
+ if (match === undefined) {
71
+ throw new FinTsProtocolError('The bank returned balances, but none for the requested account');
72
+ }
73
+ return match;
74
+ }
75
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/session/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { LoginGuard, RequestKind } from './login-guard.js';
2
+ import type { BankResponse, DialogHandle, Exchange, ResponseProtocol, StartWithOrder } from './protocol.js';
3
+ import type { SessionState } from './session-state.js';
4
+ import type { UserPrompts } from './user-prompts.js';
5
+ /** Checks what the bank answers and completes the approvals it asks for. The `LoginGuard` judges what errors mean. */
6
+ export declare class ResponseHandler<R extends BankResponse> {
7
+ private readonly protocol;
8
+ private readonly state;
9
+ private readonly prompts;
10
+ private readonly guard;
11
+ constructor(protocol: ResponseProtocol<R>, state: SessionState, prompts: UserPrompts, guard: LoginGuard);
12
+ /** Sends `login`, the exchange that opens `dialog`, and completes the approval the bank asks for. */
13
+ startDialog(dialog: DialogHandle<R>, login: Exchange<R>): Promise<R>;
14
+ /**
15
+ * Opens `dialog` with `start`, which also sends an order, and returns the answers: the login's, then the order's where
16
+ * the order has a message of its own. Completes the approval of each before the next.
17
+ */
18
+ startDialogWith(dialog: DialogHandle<R>, start: StartWithOrder<R>): Promise<R[]>;
19
+ /** Receives `response`, the answer to an order in `dialog`, and completes the approval the bank asks for. */
20
+ complete(dialog: DialogHandle<R>, response: R): Promise<R>;
21
+ /**
22
+ * Receives `response`, the answer to a request of `kind` in `dialog`: keeps its parameter data, even alongside errors,
23
+ * since the remedy for a refused login may need them; passes its notices on; and throws its errors once the guard has
24
+ * judged them (`LoginGuard.judge`).
25
+ */
26
+ receive(dialog: DialogHandle<R>, response: R, kind: RequestKind): void;
27
+ /**
28
+ * Passes the bank's messages in `response` to the user: all an anonymous dialog tells, since the TAN methods it lists
29
+ * are not those of a user.
30
+ */
31
+ showBankMessages(response: R): void;
32
+ private start;
33
+ /**
34
+ * Ends `dialog`, whose login brought new login data, and stops the client from logging in with the old ones
35
+ * (Rückmeldungscodes C.6).
36
+ */
37
+ private retireLoginData;
38
+ /**
39
+ * Receives `response`, the answer to a request of `kind`, then completes the approval it asks for; returns it joined
40
+ * with the response that completes the approval.
41
+ */
42
+ private settle;
43
+ /** Passes on the notices in `response`: the TAN methods the user may use (3920), the bank's messages and warnings. */
44
+ private readNotices;
45
+ private enterTan;
46
+ private awaitAppApproval;
47
+ }
48
+ //# sourceMappingURL=response-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../src/session/response-handler.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAY,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACtH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,sHAAsH;AACtH,qBAAa,eAAe,CAAC,CAAC,SAAS,YAAY;IAE/C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAHL,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC7B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,UAAU;IAGpC,qGAAqG;IACrG,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpE;;;OAGG;IACG,eAAe,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAOtF,6GAA6G;IAC7G,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI1D;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IAUtE;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;YAIrB,KAAK;IAMnB;;;OAGG;YACW,eAAe;IAO7B;;;OAGG;YACW,MAAM;IAUpB,sHAAsH;IACtH,OAAO,CAAC,WAAW;YAOL,QAAQ;IAYtB,OAAO,CAAC,gBAAgB;CASzB"}
@@ -0,0 +1,121 @@
1
+ import { bankErrorFor, FinTsLoginDataChangedError, FinTsTanCancelledError } from '../core/errors.js';
2
+ import { allowedTanMethodsIn, FeedbackCodes, hasCode, hasErrors, userWarnings, } from '../core/feedback.js';
3
+ import { invalidArgument } from '../util/errors.js';
4
+ import { appApprovalWait } from './app-approval.js';
5
+ /** Checks what the bank answers and completes the approvals it asks for. The `LoginGuard` judges what errors mean. */
6
+ export class ResponseHandler {
7
+ protocol;
8
+ state;
9
+ prompts;
10
+ guard;
11
+ constructor(protocol, state, prompts, guard) {
12
+ this.protocol = protocol;
13
+ this.state = state;
14
+ this.prompts = prompts;
15
+ this.guard = guard;
16
+ }
17
+ /** Sends `login`, the exchange that opens `dialog`, and completes the approval the bank asks for. */
18
+ startDialog(dialog, login) {
19
+ return this.start(dialog, login, 'login');
20
+ }
21
+ /**
22
+ * Opens `dialog` with `start`, which also sends an order, and returns the answers: the login's, then the order's where
23
+ * the order has a message of its own. Completes the approval of each before the next.
24
+ */
25
+ async startDialogWith(dialog, start) {
26
+ const order = start.order;
27
+ if (order === undefined)
28
+ return [await this.start(dialog, start.login, 'loginWithOrder')];
29
+ const login = await this.startDialog(dialog, start.login);
30
+ return [login, await this.complete(dialog, await order())];
31
+ }
32
+ /** Receives `response`, the answer to an order in `dialog`, and completes the approval the bank asks for. */
33
+ complete(dialog, response) {
34
+ return this.settle(dialog, response, 'order');
35
+ }
36
+ /**
37
+ * Receives `response`, the answer to a request of `kind` in `dialog`: keeps its parameter data, even alongside errors,
38
+ * since the remedy for a refused login may need them; passes its notices on; and throws its errors once the guard has
39
+ * judged them (`LoginGuard.judge`).
40
+ */
41
+ receive(dialog, response, kind) {
42
+ this.protocol.keepParameterData(response);
43
+ this.readNotices(response);
44
+ if (!hasErrors(response.feedback))
45
+ return;
46
+ const error = bankErrorFor(response.feedback, kind === 'approval');
47
+ // Every further message of a refused login's dialog would carry the refused PIN.
48
+ if (this.guard.judge(error, kind, dialog.isActive, dialog.method))
49
+ dialog.discard();
50
+ throw error;
51
+ }
52
+ /**
53
+ * Passes the bank's messages in `response` to the user: all an anonymous dialog tells, since the TAN methods it lists
54
+ * are not those of a user.
55
+ */
56
+ showBankMessages(response) {
57
+ for (const message of response.bankMessages)
58
+ this.prompts.showBankMessage(message);
59
+ }
60
+ async start(dialog, login, kind) {
61
+ const response = await this.settle(dialog, await login(), kind);
62
+ if (hasCode(response.feedback, FeedbackCodes.newLoginData))
63
+ await this.retireLoginData(dialog, response.feedback);
64
+ return response;
65
+ }
66
+ /**
67
+ * Ends `dialog`, whose login brought new login data, and stops the client from logging in with the old ones
68
+ * (Rückmeldungscodes C.6).
69
+ */
70
+ async retireLoginData(dialog, feedback) {
71
+ await dialog.end();
72
+ const error = new FinTsLoginDataChangedError(feedback);
73
+ this.guard.refuse(error);
74
+ throw error;
75
+ }
76
+ /**
77
+ * Receives `response`, the answer to a request of `kind`, then completes the approval it asks for; returns it joined
78
+ * with the response that completes the approval.
79
+ */
80
+ async settle(dialog, response, kind) {
81
+ this.receive(dialog, response, kind);
82
+ const approval = dialog.approvalAskedIn(response);
83
+ if (approval === undefined)
84
+ return response;
85
+ const approved = approval.challenge.isDecoupled
86
+ ? await this.awaitAppApproval(dialog, approval)
87
+ : await this.enterTan(dialog, approval);
88
+ return this.protocol.combine(response, approved);
89
+ }
90
+ /** Passes on the notices in `response`: the TAN methods the user may use (3920), the bank's messages and warnings. */
91
+ readNotices(response) {
92
+ const allowed = allowedTanMethodsIn(response.feedback);
93
+ if (allowed.length > 0)
94
+ this.state.rememberAllowedMethods(allowed);
95
+ this.showBankMessages(response);
96
+ for (const warning of userWarnings(response.feedback))
97
+ this.prompts.showWarning(warning);
98
+ }
99
+ async enterTan(dialog, approval) {
100
+ const answer = await this.prompts.askTan(approval.challenge);
101
+ if (answer.kind === 'approved') {
102
+ throw invalidArgument('Answered a TAN challenge with an approval in the banking app', 'tanCallback');
103
+ }
104
+ const tan = answer.kind === 'tan' ? answer.tan.trim() : '';
105
+ if (tan === '')
106
+ throw new FinTsTanCancelledError();
107
+ const response = await approval.submitTan(tan);
108
+ this.receive(dialog, response, 'approval');
109
+ return response;
110
+ }
111
+ awaitAppApproval(dialog, approval) {
112
+ return appApprovalWait(approval, {
113
+ ask: (challenge) => this.prompts.askTan(challenge),
114
+ pause: (delayMs, interrupt) => this.prompts.pause(delayMs, interrupt),
115
+ receive: (response) => {
116
+ this.receive(dialog, response, 'approval');
117
+ },
118
+ }).run();
119
+ }
120
+ }
121
+ //# sourceMappingURL=response-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.js","sourceRoot":"","sources":["../../src/session/response-handler.ts"],"names":[],"mappings":"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"}