lib-fints 1.1.2 → 1.2.1
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/README.md +5 -0
- package/dist/client.js +33 -0
- package/dist/dialog.js +1 -7
- package/dist/index.js +1 -0
- package/dist/interactions/portfolioInteraction.js +57 -0
- package/dist/mt535parser.js +196 -0
- package/dist/segments/HIWPD.js +15 -0
- package/dist/segments/HKWPD.js +23 -0
- package/dist/segments/registry.js +4 -0
- package/dist/tests/HIWPD.test.js +25 -0
- package/dist/tests/HKWPD.test.js +38 -0
- package/dist/tests/mt535parser.test.js +157 -0
- package/dist/types/client.d.ts +24 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/dialog.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/interactions/portfolioInteraction.d.ts +39 -0
- package/dist/types/interactions/portfolioInteraction.d.ts.map +1 -0
- package/dist/types/mt535parser.d.ts +44 -0
- package/dist/types/mt535parser.d.ts.map +1 -0
- package/dist/types/segments/HIWPD.d.ts +22 -0
- package/dist/types/segments/HIWPD.d.ts.map +1 -0
- package/dist/types/segments/HKWPD.d.ts +43 -0
- package/dist/types/segments/HKWPD.d.ts.map +1 -0
- package/dist/types/segments/registry.d.ts.map +1 -1
- package/dist/types/tests/HIWPD.test.d.ts +2 -0
- package/dist/types/tests/HIWPD.test.d.ts.map +1 -0
- package/dist/types/tests/HKWPD.test.d.ts +2 -0
- package/dist/types/tests/HKWPD.test.d.ts.map +1 -0
- package/dist/types/tests/mt535parser.test.d.ts +2 -0
- package/dist/types/tests/mt535parser.test.d.ts.map +1 -0
- package/package.json +7 -7
- package/dist/httpClientNode.js +0 -59
- package/dist/types/httpClientNode.d.ts +0 -8
- package/dist/types/httpClientNode.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
[](https://github.com/robocode13/lib-fints/actions/workflows/build-test.yml)
|
|
1
2
|
# Lib-FinTS
|
|
2
3
|
|
|
3
4
|
A Typescript/Javascript client library for Online-Banking via the FinTS 3.0 protocol with PIN/TAN, supporting PSD2 and decoupled TAN methods. The library has no dependencies on other libraries
|
|
@@ -86,6 +87,9 @@ const balanceResponse = await client.getAccountBalance(account.accountNumber);
|
|
|
86
87
|
|
|
87
88
|
// fetch all available statements
|
|
88
89
|
const statementResponse = await client.getAccountStatements(account.accountNumber);
|
|
90
|
+
|
|
91
|
+
// or fetch portfolio from a securities account
|
|
92
|
+
client.getPortfolio(account.accountNumber);
|
|
89
93
|
```
|
|
90
94
|
|
|
91
95
|
These are only the most basic steps needed to retrieve information from the bank. There are still some unanswered questions like "how to handle TANs" or "how to avoid synchronizations every time you start a new session". These are explained in the corresponding sections below.
|
|
@@ -191,6 +195,7 @@ This will print out all sent messages and received responses to the console in a
|
|
|
191
195
|
- Synchronize bank and account information
|
|
192
196
|
- Fetching account balances
|
|
193
197
|
- Fetching account statements
|
|
198
|
+
- Fetching the portfolio of a securities account
|
|
194
199
|
|
|
195
200
|
Implementing further transactions should be straight forward and contributions are highly appreciated
|
|
196
201
|
|
package/dist/client.js
CHANGED
|
@@ -2,10 +2,12 @@ import { Dialog } from './dialog.js';
|
|
|
2
2
|
import { HKTAB } from './segments/HKTAB.js';
|
|
3
3
|
import { StatementInteraction } from './interactions/statementInteraction.js';
|
|
4
4
|
import { BalanceInteraction } from './interactions/balanceInteraction.js';
|
|
5
|
+
import { PortfolioInteraction } from './interactions/portfolioInteraction.js';
|
|
5
6
|
import { FinTSConfig } from './config.js';
|
|
6
7
|
import { TanMediaInteraction } from './interactions/tanMediaInteraction.js';
|
|
7
8
|
import { HKSAL } from './segments/HKSAL.js';
|
|
8
9
|
import { HKKAZ } from './segments/HKKAZ.js';
|
|
10
|
+
import { HKWPD } from './segments/HKWPD.js';
|
|
9
11
|
import { InitDialogInteraction } from './interactions/initDialogInteraction.js';
|
|
10
12
|
/**
|
|
11
13
|
* A client to communicate with a bank over the FinTS protocol
|
|
@@ -128,6 +130,37 @@ export class FinTSClient {
|
|
|
128
130
|
async getAccountStatementsWithTan(tanReference, tan) {
|
|
129
131
|
return this.continueCustomerInteractionWithTan(tanReference, tan);
|
|
130
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Checks if the bank supports fetching portfolio information in general or for the given account number when provided
|
|
135
|
+
* @param accountNumber when the account number is provided, checks if the account supports fetching of portfolio information
|
|
136
|
+
* @returns true if the bank (and account) supports fetching portfolio information
|
|
137
|
+
*/
|
|
138
|
+
canGetPortfolio(accountNumber) {
|
|
139
|
+
return accountNumber
|
|
140
|
+
? this.config.isAccountTransactionSupported(accountNumber, HKWPD.Id)
|
|
141
|
+
: this.config.isTransactionSupported(HKWPD.Id);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Fetches the portfolio information for the given depot account number
|
|
145
|
+
* @param accountNumber - the depot account number to fetch the portfolio for, must be an account available in the config.bankingInformation.UPD.accounts
|
|
146
|
+
* @param currency - optional currency filter for the portfolio statement
|
|
147
|
+
* @param priceQuality - optional price quality filter ('1' for real-time, '2' for delayed)
|
|
148
|
+
* @param maxEntries - optional maximum number of entries to retrieve
|
|
149
|
+
* @returns a portfolio response containing holdings and total value
|
|
150
|
+
*/
|
|
151
|
+
async getPortfolio(accountNumber, currency, priceQuality, maxEntries) {
|
|
152
|
+
return this.startCustomerOrderInteraction(new PortfolioInteraction(accountNumber, currency, priceQuality, maxEntries));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Continues the portfolio fetching when a TAN is required
|
|
156
|
+
* @param tanReference The TAN reference provided in the first call's response
|
|
157
|
+
|
|
158
|
+
* @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
|
|
159
|
+
* @returns a portfolio response containing holdings and total value
|
|
160
|
+
*/
|
|
161
|
+
async getPortfolioWithTan(tanReference, tan) {
|
|
162
|
+
return this.continueCustomerInteractionWithTan(tanReference, tan);
|
|
163
|
+
}
|
|
131
164
|
async startCustomerOrderInteraction(interaction) {
|
|
132
165
|
const dialog = new Dialog(this.config);
|
|
133
166
|
const syncResponse = await this.initDialog(dialog, false, interaction);
|
package/dist/dialog.js
CHANGED
|
@@ -7,7 +7,6 @@ import { HKTAN } from './segments/HKTAN.js';
|
|
|
7
7
|
import { HNHBK } from './segments/HNHBK.js';
|
|
8
8
|
import { decode } from './segment.js';
|
|
9
9
|
import { PARTED } from './partedSegment.js';
|
|
10
|
-
import { HttpClientNode } from './httpClientNode.js';
|
|
11
10
|
export class Dialog {
|
|
12
11
|
config;
|
|
13
12
|
dialogId = '0';
|
|
@@ -182,11 +181,6 @@ export class Dialog {
|
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
getHttpClient() {
|
|
185
|
-
|
|
186
|
-
return new HttpClient(this.config.bankingUrl, this.config.debugEnabled);
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
return new HttpClientNode(this.config.bankingUrl, this.config.debugEnabled);
|
|
190
|
-
}
|
|
184
|
+
return new HttpClient(this.config.bankingUrl, this.config.debugEnabled);
|
|
191
185
|
}
|
|
192
186
|
}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CustomerOrderInteraction, } from './customerInteraction.js';
|
|
2
|
+
import { HKWPD } from '../segments/HKWPD.js';
|
|
3
|
+
import { HIWPD } from '../segments/HIWPD.js';
|
|
4
|
+
import { Mt535Parser } from '../mt535parser.js';
|
|
5
|
+
/**
|
|
6
|
+
* Interaction for requesting and parsing stock portfolio information (HKWPD/HIWPD)
|
|
7
|
+
*/
|
|
8
|
+
export class PortfolioInteraction extends CustomerOrderInteraction {
|
|
9
|
+
accountNumber;
|
|
10
|
+
currency;
|
|
11
|
+
priceQuality;
|
|
12
|
+
maxEntries;
|
|
13
|
+
paginationMarker;
|
|
14
|
+
constructor(accountNumber, currency, priceQuality, maxEntries, paginationMarker) {
|
|
15
|
+
super(HKWPD.Id, HIWPD.Id);
|
|
16
|
+
this.accountNumber = accountNumber;
|
|
17
|
+
this.currency = currency;
|
|
18
|
+
this.priceQuality = priceQuality;
|
|
19
|
+
this.maxEntries = maxEntries;
|
|
20
|
+
this.paginationMarker = paginationMarker;
|
|
21
|
+
}
|
|
22
|
+
createSegments(config) {
|
|
23
|
+
const bankAccount = config.getBankAccount(this.accountNumber);
|
|
24
|
+
if (!config.isAccountTransactionSupported(this.accountNumber, this.segId)) {
|
|
25
|
+
throw Error(`Account ${this.accountNumber} does not support business transaction '${this.segId}'`);
|
|
26
|
+
}
|
|
27
|
+
const depotAccount = { ...bankAccount, iban: undefined }; // HKWPD uses KTV which doesn't have IBAN
|
|
28
|
+
const version = config.getMaxSupportedTransactionVersion(HKWPD.Id);
|
|
29
|
+
if (!version) {
|
|
30
|
+
throw Error(`There is no supported version for business transaction '${HKWPD.Id}'`);
|
|
31
|
+
}
|
|
32
|
+
const hkwpd = {
|
|
33
|
+
header: { segId: HKWPD.Id, segNr: 0, version: version },
|
|
34
|
+
depot: depotAccount,
|
|
35
|
+
currency: this.currency,
|
|
36
|
+
priceQuality: this.priceQuality,
|
|
37
|
+
maxEntries: this.maxEntries,
|
|
38
|
+
paginationMarker: this.paginationMarker,
|
|
39
|
+
};
|
|
40
|
+
return [hkwpd];
|
|
41
|
+
}
|
|
42
|
+
handleResponse(response, clientResponse) {
|
|
43
|
+
const hiwpdSegment = response.findSegment(HIWPD.Id);
|
|
44
|
+
if (hiwpdSegment?.portfolioStatement) {
|
|
45
|
+
try {
|
|
46
|
+
// Parse the MT535 data
|
|
47
|
+
const parser = new Mt535Parser(hiwpdSegment.portfolioStatement);
|
|
48
|
+
clientResponse.portfolioStatement = parser.parse();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.warn('Failed to parse MT535 portfolio statement:', error);
|
|
52
|
+
// Fallback: provide raw data if parsing fails
|
|
53
|
+
clientResponse.rawMT535Data = hiwpdSegment.portfolioStatement;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
export var TokenType535;
|
|
2
|
+
(function (TokenType535) {
|
|
3
|
+
TokenType535["DepotValueBlock"] = "DepotValueBlock";
|
|
4
|
+
TokenType535["DepotValueCurrency"] = "DepotValueCurrency";
|
|
5
|
+
TokenType535["FinBlock"] = "FinBlock";
|
|
6
|
+
TokenType535["SecurityIdentification"] = "SecurityIdentification";
|
|
7
|
+
TokenType535["AcquisitionPrice"] = "AcquisitionPrice";
|
|
8
|
+
TokenType535["PriceBlock"] = "PriceBlock";
|
|
9
|
+
TokenType535["AmountBlock"] = "AmountBlock";
|
|
10
|
+
TokenType535["DateTimeBlock"] = "DateTimeBlock";
|
|
11
|
+
TokenType535["DateString"] = "DateString";
|
|
12
|
+
TokenType535["TimeString"] = "TimeString";
|
|
13
|
+
})(TokenType535 || (TokenType535 = {}));
|
|
14
|
+
const tokens535 = {
|
|
15
|
+
[TokenType535.DepotValueBlock]: /:16R:ADDINFO(.*?):16S:ADDINFO/ms,
|
|
16
|
+
[TokenType535.DepotValueCurrency]: /EUR(.*)/ms,
|
|
17
|
+
[TokenType535.FinBlock]: /:16R:FIN(.*?):16S:FIN/gms,
|
|
18
|
+
[TokenType535.SecurityIdentification]: /:35B:(.*?):/ms,
|
|
19
|
+
[TokenType535.AcquisitionPrice]: /:70E::HOLD\/\/\d*STK2(\d*),(\d*)\+([A-Z]{3})/ms,
|
|
20
|
+
[TokenType535.PriceBlock]: /:90([AB])::(.*?):/ms,
|
|
21
|
+
[TokenType535.AmountBlock]: /:93B::(.*?):/ms,
|
|
22
|
+
[TokenType535.DateTimeBlock]: /:98([AC])::(.*?):/ms,
|
|
23
|
+
[TokenType535.DateString]: /(\d{4})(\d{2})(\d{2})/,
|
|
24
|
+
[TokenType535.TimeString]: /^.{14}(\d{2})(\d{2})(\d{2})/ms,
|
|
25
|
+
};
|
|
26
|
+
export class Mt535Parser {
|
|
27
|
+
rawData;
|
|
28
|
+
cleanedRawData;
|
|
29
|
+
constructor(rawData) {
|
|
30
|
+
this.rawData = rawData;
|
|
31
|
+
// The divider can be either \r\n or @@
|
|
32
|
+
const crlfCount = (rawData.match(/\r\n-/g) || []).length;
|
|
33
|
+
const atAtCount = (rawData.match(/@@-/g) || []).length;
|
|
34
|
+
const divider = crlfCount > atAtCount ? '\r\n' : '@@';
|
|
35
|
+
// Remove dividers that are not followed by a colon (tag indicator)
|
|
36
|
+
const regex = new RegExp(divider + '([^:])', 'gms');
|
|
37
|
+
this.cleanedRawData = rawData.replace(regex, '$1');
|
|
38
|
+
}
|
|
39
|
+
parse() {
|
|
40
|
+
const result = {
|
|
41
|
+
holdings: [],
|
|
42
|
+
};
|
|
43
|
+
// Parse total depot value
|
|
44
|
+
result.totalValue = this.parseDepotValue();
|
|
45
|
+
// Parse individual holdings
|
|
46
|
+
result.holdings = this.parseHoldings();
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
parseDepotValue() {
|
|
50
|
+
const addInfoMatch = this.cleanedRawData.match(tokens535[TokenType535.DepotValueBlock]);
|
|
51
|
+
if (addInfoMatch) {
|
|
52
|
+
const eurMatch = addInfoMatch[1].match(tokens535[TokenType535.DepotValueCurrency]);
|
|
53
|
+
if (eurMatch) {
|
|
54
|
+
return parseFloat(eurMatch[1].replace(',', '.'));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
parseHoldings() {
|
|
60
|
+
const holdings = [];
|
|
61
|
+
const finBlocks = this.cleanedRawData.match(tokens535[TokenType535.FinBlock]);
|
|
62
|
+
if (!finBlocks) {
|
|
63
|
+
return holdings;
|
|
64
|
+
}
|
|
65
|
+
for (const block of finBlocks) {
|
|
66
|
+
const holding = this.parseHolding(block);
|
|
67
|
+
if (holding) {
|
|
68
|
+
holdings.push(holding);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return holdings;
|
|
72
|
+
}
|
|
73
|
+
parseHolding(block) {
|
|
74
|
+
const holding = {};
|
|
75
|
+
// Parse ISIN, WKN & Name from :35B:
|
|
76
|
+
// :35B:ISIN DE0005190003/DE/519000BAY.MOTOREN WERKE AG ST
|
|
77
|
+
this.parseSecurityIdentification(block, holding);
|
|
78
|
+
// Parse acquisition price from :70E::HOLD//
|
|
79
|
+
this.parseAcquisitionPrice(block, holding);
|
|
80
|
+
// Parse current price from :90B: or :90A:
|
|
81
|
+
this.parsePrice(block, holding);
|
|
82
|
+
// Parse amount from :93B:
|
|
83
|
+
this.parseAmount(block, holding);
|
|
84
|
+
// Parse date/time from :98A: or :98C:
|
|
85
|
+
this.parseDateTime(block, holding);
|
|
86
|
+
// Calculate value if we have price and amount
|
|
87
|
+
if (holding.amount !== undefined && holding.price !== undefined) {
|
|
88
|
+
// For all currencies, value is price multiplied by amount
|
|
89
|
+
holding.value = holding.price * holding.amount;
|
|
90
|
+
}
|
|
91
|
+
return holding;
|
|
92
|
+
}
|
|
93
|
+
parseSecurityIdentification(block, holding) {
|
|
94
|
+
const match = block.match(tokens535[TokenType535.SecurityIdentification]);
|
|
95
|
+
if (match) {
|
|
96
|
+
const content = match[1];
|
|
97
|
+
// ISIN: characters 5-16 (12 chars)
|
|
98
|
+
const isinMatch = content.match(/^.{5}(.{12})/ms);
|
|
99
|
+
if (isinMatch) {
|
|
100
|
+
holding.isin = isinMatch[1];
|
|
101
|
+
}
|
|
102
|
+
// WKN: characters 21-26 (6 chars)
|
|
103
|
+
const wknMatch = content.match(/^.{21}(.{6})/ms);
|
|
104
|
+
if (wknMatch) {
|
|
105
|
+
holding.wkn = wknMatch[1];
|
|
106
|
+
}
|
|
107
|
+
// Name: everything from character 27 onwards
|
|
108
|
+
const nameMatch = content.match(/^.{27}(.*)/ms);
|
|
109
|
+
if (nameMatch) {
|
|
110
|
+
holding.name = nameMatch[1].trim();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
parseAcquisitionPrice(block, holding) {
|
|
115
|
+
const match = block.match(tokens535[TokenType535.AcquisitionPrice]);
|
|
116
|
+
if (match) {
|
|
117
|
+
holding.acquisitionPrice = parseFloat(`${match[1]}.${match[2]}`);
|
|
118
|
+
if (!holding.currency) {
|
|
119
|
+
holding.currency = match[3];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
parsePrice(block, holding) {
|
|
124
|
+
const match = block.match(tokens535[TokenType535.PriceBlock]);
|
|
125
|
+
if (match) {
|
|
126
|
+
const type = match[1];
|
|
127
|
+
const content = match[2];
|
|
128
|
+
if (type === 'B') {
|
|
129
|
+
// Currency from characters 11-13 (3 chars)
|
|
130
|
+
const currencyMatch = content.match(/^.{11}(.{3})/ms);
|
|
131
|
+
if (currencyMatch) {
|
|
132
|
+
holding.currency = currencyMatch[1];
|
|
133
|
+
}
|
|
134
|
+
// Price from character 14 onwards
|
|
135
|
+
const priceMatch = content.match(/^.{14}(.*)/ms);
|
|
136
|
+
if (priceMatch) {
|
|
137
|
+
holding.price = parseFloat(priceMatch[1].replace(',', '.'));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (type === 'A') {
|
|
141
|
+
holding.currency = '%';
|
|
142
|
+
// Price from character 11 onwards
|
|
143
|
+
const priceMatch = content.match(/^.{11}(.*)/ms);
|
|
144
|
+
if (priceMatch) {
|
|
145
|
+
holding.price = parseFloat(priceMatch[1].replace(',', '.')) / 100;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
parseAmount(block, holding) {
|
|
151
|
+
const match = block.match(tokens535[TokenType535.AmountBlock]);
|
|
152
|
+
if (match) {
|
|
153
|
+
// Amount from character 11 onwards
|
|
154
|
+
const amountMatch = match[1].match(/^.{11}(.*)/ms);
|
|
155
|
+
if (amountMatch) {
|
|
156
|
+
holding.amount = parseFloat(amountMatch[1].replace(',', '.'));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
parseDateTime(block, holding) {
|
|
161
|
+
const match = block.match(tokens535[TokenType535.DateTimeBlock]);
|
|
162
|
+
if (match) {
|
|
163
|
+
const type = match[1];
|
|
164
|
+
const content = match[2];
|
|
165
|
+
// Date from characters 6-13 (8 chars: YYYYMMDD)
|
|
166
|
+
const dateMatch = content.match(tokens535[TokenType535.DateString]);
|
|
167
|
+
if (dateMatch) {
|
|
168
|
+
const parsedDate = this.parseDate(dateMatch[0]);
|
|
169
|
+
if (type === 'C') {
|
|
170
|
+
// :98C: has a time component HHMMSS starting at character 14
|
|
171
|
+
const timeMatch = content.match(tokens535[TokenType535.TimeString]);
|
|
172
|
+
if (timeMatch) {
|
|
173
|
+
parsedDate.setHours(parseInt(timeMatch[1]), parseInt(timeMatch[2]), parseInt(timeMatch[3]));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// :98A: time defaults to 00:00:00
|
|
178
|
+
parsedDate.setHours(0, 0, 0, 0);
|
|
179
|
+
}
|
|
180
|
+
holding.date = parsedDate;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
parseDate(dateString) {
|
|
185
|
+
const match = dateString.match(tokens535[TokenType535.DateString]);
|
|
186
|
+
if (!match) {
|
|
187
|
+
throw new Error(`Invalid date format: ${dateString}`);
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
return new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
throw new Error(`Invalid date: ${dateString}`, { cause: error });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Binary } from '../dataElements/Binary.js';
|
|
2
|
+
import { SegmentDefinition } from '../segmentDefinition.js';
|
|
3
|
+
/**
|
|
4
|
+
* Geschäftsvorfälle: C.4.3.1 Kreditinstitutsrückmeldung
|
|
5
|
+
* Version: 6
|
|
6
|
+
*/
|
|
7
|
+
export class HIWPD extends SegmentDefinition {
|
|
8
|
+
static Id = 'HIWPD';
|
|
9
|
+
static Version = 6;
|
|
10
|
+
constructor() {
|
|
11
|
+
super(HIWPD.Id);
|
|
12
|
+
}
|
|
13
|
+
version = HIWPD.Version;
|
|
14
|
+
elements = [new Binary('portfolioStatement', 1, 1)];
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AccountGroup } from '../dataGroups/Account.js';
|
|
2
|
+
import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
|
|
3
|
+
import { Numeric } from '../dataElements/Numeric.js';
|
|
4
|
+
import { SegmentDefinition } from '../segmentDefinition.js';
|
|
5
|
+
/**
|
|
6
|
+
* Geschäftsvorfälle: C.4.3.1 Depotaufstellung
|
|
7
|
+
* Version: 6
|
|
8
|
+
*/
|
|
9
|
+
export class HKWPD extends SegmentDefinition {
|
|
10
|
+
static Id = 'HKWPD';
|
|
11
|
+
static Version = 6;
|
|
12
|
+
constructor() {
|
|
13
|
+
super(HKWPD.Id);
|
|
14
|
+
}
|
|
15
|
+
version = HKWPD.Version;
|
|
16
|
+
elements = [
|
|
17
|
+
new AccountGroup('depot', 1, 1),
|
|
18
|
+
new AlphaNumeric('currency', 0, 1, 3),
|
|
19
|
+
new AlphaNumeric('priceQuality', 0, 1, 1),
|
|
20
|
+
new Numeric('maxEntries', 0, 1, 4),
|
|
21
|
+
new AlphaNumeric('paginationMarker', 0, 1, 35),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
@@ -27,6 +27,8 @@ import { HKKAZ } from './HKKAZ.js';
|
|
|
27
27
|
import { HIKAZ } from './HIKAZ.js';
|
|
28
28
|
import { HIKAZS } from './HIKAZS.js';
|
|
29
29
|
import { HITAB } from './HITAB.js';
|
|
30
|
+
import { HKWPD } from './HKWPD.js';
|
|
31
|
+
import { HIWPD } from './HIWPD.js';
|
|
30
32
|
import { UNKNOW } from '../unknownSegment.js';
|
|
31
33
|
import { PARTED } from '../partedSegment.js';
|
|
32
34
|
const registry = new Map();
|
|
@@ -60,6 +62,8 @@ export function registerSegments() {
|
|
|
60
62
|
registerSegmentDefinition(new HKKAZ());
|
|
61
63
|
registerSegmentDefinition(new HIKAZ());
|
|
62
64
|
registerSegmentDefinition(new HIKAZS());
|
|
65
|
+
registerSegmentDefinition(new HKWPD());
|
|
66
|
+
registerSegmentDefinition(new HIWPD());
|
|
63
67
|
registerSegmentDefinition(new UNKNOW());
|
|
64
68
|
registerSegmentDefinition(new PARTED());
|
|
65
69
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { registerSegments } from '../segments/registry.js';
|
|
3
|
+
import { decode, encode } from '../segment.js';
|
|
4
|
+
registerSegments();
|
|
5
|
+
describe('HIWPD', () => {
|
|
6
|
+
it('decode and encode roundtrip matches', () => {
|
|
7
|
+
const portfolioData = 'U29tZSBTd2lmdCBNVCA1MzUvNTcxIGRhdGE=';
|
|
8
|
+
const text = `HIWPD:1:6+${portfolioData}'`;
|
|
9
|
+
const segment = decode(text);
|
|
10
|
+
expect(segment.portfolioStatement).toBe(portfolioData);
|
|
11
|
+
const expectedEncodedText = `HIWPD:1:6+@${portfolioData.length}@${portfolioData}'`;
|
|
12
|
+
expect(encode(segment)).toBe(expectedEncodedText);
|
|
13
|
+
});
|
|
14
|
+
it('handles empty portfolio data', () => {
|
|
15
|
+
const text = "HIWPD:1:6+@@'";
|
|
16
|
+
const segment = decode(text);
|
|
17
|
+
expect(segment.portfolioStatement).toBe('');
|
|
18
|
+
});
|
|
19
|
+
it('handles large portfolio data', () => {
|
|
20
|
+
const largeData = 'A'.repeat(1000);
|
|
21
|
+
const text = `HIWPD:1:6+${largeData}'`;
|
|
22
|
+
const segment = decode(text);
|
|
23
|
+
expect(segment.portfolioStatement).toBe(largeData);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { registerSegments } from '../segments/registry.js';
|
|
3
|
+
import { decode, encode } from '../segment.js';
|
|
4
|
+
registerSegments();
|
|
5
|
+
describe('HKWPD', () => {
|
|
6
|
+
it('decode and encode roundtrip matches with all fields', () => {
|
|
7
|
+
const text = "HKWPD:2:6+12345678901234567890:EUR:276:280+EUR+1+100+NextMarkerABC123'";
|
|
8
|
+
const segment = decode(text);
|
|
9
|
+
expect(segment.depot.accountNumber).toBe('12345678901234567890');
|
|
10
|
+
expect(segment.depot.subAccountId).toBe('EUR');
|
|
11
|
+
expect(segment.depot.bank.country).toBe(276);
|
|
12
|
+
expect(segment.depot.bank.bankId).toBe('280');
|
|
13
|
+
expect(segment.currency).toBe('EUR');
|
|
14
|
+
expect(segment.priceQuality).toBe('1');
|
|
15
|
+
expect(segment.maxEntries).toBe(100);
|
|
16
|
+
expect(segment.paginationMarker).toBe('NextMarkerABC123');
|
|
17
|
+
expect(encode(segment)).toBe(text);
|
|
18
|
+
});
|
|
19
|
+
it('decode and encode roundtrip matches with minimal fields', () => {
|
|
20
|
+
const text = "HKWPD:1:6+9876543210::276:280'";
|
|
21
|
+
const segment = decode(text);
|
|
22
|
+
expect(segment.depot.accountNumber).toBe('9876543210');
|
|
23
|
+
expect(segment.depot.subAccountId).toBeUndefined();
|
|
24
|
+
expect(segment.depot.bank.country).toBe(276);
|
|
25
|
+
expect(segment.depot.bank.bankId).toBe('280');
|
|
26
|
+
expect(segment.currency).toBeUndefined();
|
|
27
|
+
expect(segment.priceQuality).toBeUndefined();
|
|
28
|
+
expect(segment.maxEntries).toBeUndefined();
|
|
29
|
+
expect(segment.paginationMarker).toBeUndefined();
|
|
30
|
+
const encoded = encode(segment);
|
|
31
|
+
expect(encoded).toBe("HKWPD:1:6+9876543210::276:280'");
|
|
32
|
+
const decodedAgain = decode(encoded);
|
|
33
|
+
expect(decodedAgain.depot.accountNumber).toBe('9876543210');
|
|
34
|
+
expect(decodedAgain.depot.subAccountId).toBeUndefined();
|
|
35
|
+
expect(decodedAgain.depot.bank.country).toBe(276);
|
|
36
|
+
expect(decodedAgain.depot.bank.bankId).toBe('280');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { Mt535Parser } from '../mt535parser.js';
|
|
3
|
+
describe('Mt535Parser', () => {
|
|
4
|
+
it('parses a MT535 input string with depot value and multiple holdings', () => {
|
|
5
|
+
const input = ':16R:ADDINFO\r\n' +
|
|
6
|
+
'EUR125000,50\r\n' +
|
|
7
|
+
':16S:ADDINFO\r\n' +
|
|
8
|
+
// Holding 1 (BMW)
|
|
9
|
+
':16R:FIN\r\n' +
|
|
10
|
+
':35B:ISIN DE0005190003/DE/519000BAY.MOTOREN WERKE AG ST:\r\n' +
|
|
11
|
+
':70E::HOLD//100STK275,30+EUR\r\n' +
|
|
12
|
+
':90B::PREFIX_11_CEUR100,50:\r\n' +
|
|
13
|
+
':93B::QTY/AVALBLX100,:\r\n' +
|
|
14
|
+
':98A::SETT//DTE20231101:\r\n' +
|
|
15
|
+
':16S:FIN\r\n' +
|
|
16
|
+
// Holding 2 (Apple)
|
|
17
|
+
':16R:FIN\r\n' +
|
|
18
|
+
':35B:ISIN US0378331005/US/037833Apple Inc. Common Stock:\r\n' +
|
|
19
|
+
':70E::HOLD//50STK2150,75+USD\r\n' +
|
|
20
|
+
':90A::PRIC/RATE_X85,50:\r\n' +
|
|
21
|
+
':93B::QTY/AVALBLX50,:\r\n' +
|
|
22
|
+
':98C::TRADTE20231101143000:\r\n' +
|
|
23
|
+
':16S:FIN\r\n';
|
|
24
|
+
const parser = new Mt535Parser(input);
|
|
25
|
+
const statement = parser.parse();
|
|
26
|
+
// Test depot value
|
|
27
|
+
expect(statement.totalValue).toBe(125000.5);
|
|
28
|
+
expect(statement.holdings).toHaveLength(2);
|
|
29
|
+
// Test first holding (BMW)
|
|
30
|
+
const bmwHolding = statement.holdings[0];
|
|
31
|
+
expect(bmwHolding.isin).toBe('DE0005190003');
|
|
32
|
+
expect(bmwHolding.wkn).toBe('519000');
|
|
33
|
+
expect(bmwHolding.name).toBe('BAY.MOTOREN WERKE AG ST');
|
|
34
|
+
expect(bmwHolding.acquisitionPrice).toBe(75.3);
|
|
35
|
+
expect(bmwHolding.price).toBe(100.5);
|
|
36
|
+
expect(bmwHolding.currency).toBe('EUR');
|
|
37
|
+
expect(bmwHolding.amount).toBe(100);
|
|
38
|
+
expect(bmwHolding.value).toBe(10050);
|
|
39
|
+
expect(bmwHolding.date).toEqual(new Date(2023, 10, 1, 0, 0, 0));
|
|
40
|
+
// Test second holding (Apple)
|
|
41
|
+
const appleHolding = statement.holdings[1];
|
|
42
|
+
expect(appleHolding.isin).toBe('US0378331005');
|
|
43
|
+
expect(appleHolding.wkn).toBe('037833');
|
|
44
|
+
expect(appleHolding.name).toBe('Apple Inc. Common Stock');
|
|
45
|
+
expect(appleHolding.acquisitionPrice).toBe(150.75);
|
|
46
|
+
expect(appleHolding.price).toBe(0.855);
|
|
47
|
+
expect(appleHolding.currency).toBe('%');
|
|
48
|
+
expect(appleHolding.amount).toBe(50);
|
|
49
|
+
expect(appleHolding.value).toBe(42.75);
|
|
50
|
+
expect(appleHolding.date).toEqual(new Date(2023, 10, 1, 14, 30, 0));
|
|
51
|
+
});
|
|
52
|
+
it('parses MT535 with @@ dividers and different data points', () => {
|
|
53
|
+
const input = ':16R:ADDINFO@@' +
|
|
54
|
+
'EUR50000,25@@' +
|
|
55
|
+
':16S:ADDINFO@@' +
|
|
56
|
+
':16R:FIN@@' +
|
|
57
|
+
':35B:ISIN DE0007164600/DE/716460SAP SE:@@' +
|
|
58
|
+
':70E::HOLD//25STK2120,80+EUR@@' +
|
|
59
|
+
':90B::UNKNOWNVALXEUR115,75:@@' +
|
|
60
|
+
':93B::SOMESTATUS_25,:@@' +
|
|
61
|
+
':98A::REGD//DTE20231215:@@' +
|
|
62
|
+
':16S:FIN@@';
|
|
63
|
+
const parser = new Mt535Parser(input);
|
|
64
|
+
const statement = parser.parse();
|
|
65
|
+
expect(statement.totalValue).toBe(50000.25);
|
|
66
|
+
expect(statement.holdings).toHaveLength(1);
|
|
67
|
+
const holding = statement.holdings[0];
|
|
68
|
+
expect(holding.isin).toBe('DE0007164600');
|
|
69
|
+
expect(holding.wkn).toBe('716460');
|
|
70
|
+
expect(holding.name).toBe('SAP SE');
|
|
71
|
+
expect(holding.acquisitionPrice).toBe(120.8);
|
|
72
|
+
expect(holding.price).toBe(115.75);
|
|
73
|
+
expect(holding.currency).toBe('EUR');
|
|
74
|
+
expect(holding.amount).toBe(25);
|
|
75
|
+
expect(holding.value).toBe(2893.75);
|
|
76
|
+
expect(holding.date).toEqual(new Date(2023, 11, 15));
|
|
77
|
+
});
|
|
78
|
+
it('handles empty input', () => {
|
|
79
|
+
const parser = new Mt535Parser('');
|
|
80
|
+
const statement = parser.parse();
|
|
81
|
+
expect(statement.totalValue).toBeUndefined();
|
|
82
|
+
expect(statement.holdings).toHaveLength(0);
|
|
83
|
+
});
|
|
84
|
+
it('handles input without depot value', () => {
|
|
85
|
+
const input = ':16R:FIN\r\n' +
|
|
86
|
+
':35B:ISIN DE0005190003/DE/519000SOME OTHER AG ST:\r\n' +
|
|
87
|
+
':90B::PREFIX_11_CEUR100,50:\r\n' +
|
|
88
|
+
':93B::QTY/AVALBLX100,:\r\n' +
|
|
89
|
+
':98A::SETT//DTE20231101:\r\n' +
|
|
90
|
+
':16S:FIN\r\n';
|
|
91
|
+
const parser = new Mt535Parser(input);
|
|
92
|
+
const statement = parser.parse();
|
|
93
|
+
expect(statement.totalValue).toBeUndefined();
|
|
94
|
+
expect(statement.holdings).toHaveLength(1);
|
|
95
|
+
expect(statement.holdings[0].isin).toBe('DE0005190003');
|
|
96
|
+
expect(statement.holdings[0].name).toBe('SOME OTHER AG ST');
|
|
97
|
+
expect(statement.holdings[0].price).toBe(100.5);
|
|
98
|
+
expect(statement.holdings[0].amount).toBe(100);
|
|
99
|
+
});
|
|
100
|
+
it('handles input without holdings', () => {
|
|
101
|
+
const input = ':16R:ADDINFO\r\n' + 'EUR75000,00\r\n' + ':16S:ADDINFO\r\n';
|
|
102
|
+
const parser = new Mt535Parser(input);
|
|
103
|
+
const statement = parser.parse();
|
|
104
|
+
expect(statement.totalValue).toBe(75000.0);
|
|
105
|
+
expect(statement.holdings).toHaveLength(0);
|
|
106
|
+
});
|
|
107
|
+
it('handles holding with minimal data (only security identification)', () => {
|
|
108
|
+
const input = ':16R:FIN\r\n' +
|
|
109
|
+
':35B:ISIN FR0000120271/FR/120271AIR LIQUIDE SA: \r\n' +
|
|
110
|
+
':16S:FIN\r\n';
|
|
111
|
+
const parser = new Mt535Parser(input);
|
|
112
|
+
const statement = parser.parse();
|
|
113
|
+
expect(statement.holdings).toHaveLength(1);
|
|
114
|
+
const holding = statement.holdings[0];
|
|
115
|
+
expect(holding.isin).toBe('FR0000120271');
|
|
116
|
+
expect(holding.wkn).toBe('120271');
|
|
117
|
+
expect(holding.name).toBe('AIR LIQUIDE SA');
|
|
118
|
+
expect(holding.price).toBeUndefined();
|
|
119
|
+
expect(holding.amount).toBeUndefined();
|
|
120
|
+
expect(holding.value).toBeUndefined();
|
|
121
|
+
expect(holding.date).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
it('calculates value correctly for percentage currency when price is from :90A', () => {
|
|
124
|
+
const input = ':16R:FIN\r\n' +
|
|
125
|
+
':35B:ISIN US0378331005/US/037833Apple Inc. Common Stock:\r\n' +
|
|
126
|
+
':90A::PRIC/RATE_X85,50:\r\n' +
|
|
127
|
+
':93B::QTY/AVALBLX100,:\r\n' +
|
|
128
|
+
':16S:FIN\r\n';
|
|
129
|
+
const parser = new Mt535Parser(input);
|
|
130
|
+
const statement = parser.parse();
|
|
131
|
+
const holding = statement.holdings[0];
|
|
132
|
+
expect(holding.currency).toBe('%');
|
|
133
|
+
expect(holding.price).toBe(0.855);
|
|
134
|
+
expect(holding.amount).toBe(100);
|
|
135
|
+
expect(holding.value).toBe(85.5);
|
|
136
|
+
});
|
|
137
|
+
it('correctly parses date and time for :98C', () => {
|
|
138
|
+
const input = ':16R:FIN\r\n' +
|
|
139
|
+
':35B:ISIN DE000BASF111/DE/BASF11BASF SE:\r\n' +
|
|
140
|
+
':98C::QUALIF20240115093045:\r\n' +
|
|
141
|
+
':16S:FIN\r\n';
|
|
142
|
+
const parser = new Mt535Parser(input);
|
|
143
|
+
const statement = parser.parse();
|
|
144
|
+
const holding = statement.holdings[0];
|
|
145
|
+
expect(holding.date).toEqual(new Date(2024, 0, 15, 9, 30, 45));
|
|
146
|
+
});
|
|
147
|
+
it('correctly parses date for :98A (time defaults to 00:00:00)', () => {
|
|
148
|
+
const input = ':16R:FIN\r\n' +
|
|
149
|
+
':35B:ISIN DE000BAY0017/DE/BAY001BAYER AG:\r\n' +
|
|
150
|
+
':98A::SETT//DTE20231005:\r\n' +
|
|
151
|
+
':16S:FIN\r\n';
|
|
152
|
+
const parser = new Mt535Parser(input);
|
|
153
|
+
const statement = parser.parse();
|
|
154
|
+
const holding = statement.holdings[0];
|
|
155
|
+
expect(holding.date).toEqual(new Date(2023, 9, 5, 0, 0, 0));
|
|
156
|
+
});
|
|
157
|
+
});
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StatementResponse } from './interactions/statementInteraction.js';
|
|
2
2
|
import { AccountBalanceResponse } from './interactions/balanceInteraction.js';
|
|
3
|
+
import { PortfolioResponse } from './interactions/portfolioInteraction.js';
|
|
3
4
|
import { FinTSConfig } from './config.js';
|
|
4
5
|
import { TanMethod } from './tanMethod.js';
|
|
5
6
|
import { InitResponse } from './interactions/initDialogInteraction.js';
|
|
@@ -79,6 +80,29 @@ export declare class FinTSClient {
|
|
|
79
80
|
* @returns an account statements response containing an array of statements
|
|
80
81
|
*/
|
|
81
82
|
getAccountStatementsWithTan(tanReference: string, tan?: string): Promise<StatementResponse>;
|
|
83
|
+
/**
|
|
84
|
+
* Checks if the bank supports fetching portfolio information in general or for the given account number when provided
|
|
85
|
+
* @param accountNumber when the account number is provided, checks if the account supports fetching of portfolio information
|
|
86
|
+
* @returns true if the bank (and account) supports fetching portfolio information
|
|
87
|
+
*/
|
|
88
|
+
canGetPortfolio(accountNumber?: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Fetches the portfolio information for the given depot account number
|
|
91
|
+
* @param accountNumber - the depot account number to fetch the portfolio for, must be an account available in the config.bankingInformation.UPD.accounts
|
|
92
|
+
* @param currency - optional currency filter for the portfolio statement
|
|
93
|
+
* @param priceQuality - optional price quality filter ('1' for real-time, '2' for delayed)
|
|
94
|
+
* @param maxEntries - optional maximum number of entries to retrieve
|
|
95
|
+
* @returns a portfolio response containing holdings and total value
|
|
96
|
+
*/
|
|
97
|
+
getPortfolio(accountNumber: string, currency?: string, priceQuality?: '1' | '2', maxEntries?: number): Promise<PortfolioResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* Continues the portfolio fetching when a TAN is required
|
|
100
|
+
* @param tanReference The TAN reference provided in the first call's response
|
|
101
|
+
|
|
102
|
+
* @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
|
|
103
|
+
* @returns a portfolio response containing holdings and total value
|
|
104
|
+
*/
|
|
105
|
+
getPortfolioWithTan(tanReference: string, tan?: string): Promise<PortfolioResponse>;
|
|
82
106
|
private startCustomerOrderInteraction;
|
|
83
107
|
private continueCustomerInteractionWithTan;
|
|
84
108
|
private initDialog;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAsB,MAAM,sCAAsC,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAsB,MAAM,sCAAsC,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C,OAAO,EAAyB,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAE9F,MAAM,WAAW,mBAAoB,SAAQ,YAAY;CAAG;AAE5D;;GAEG;AACH,qBAAa,WAAW;IAOJ,MAAM,EAAE,WAAW;IANtC,OAAO,CAAC,wBAAwB,CAA0C;IAE1E;;;OAGG;gBACgB,MAAM,EAAE,WAAW;IAUtC;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAK/C;;;OAGG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1C;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwBjD;;;;;OAKG;IACG,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI1F;;;;OAIG;IACH,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMrD;;;;OAIG;IACG,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAI/E;;;;;OAKG;IACG,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAInG;;;;OAIG;IACH,uBAAuB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMxD;;;;;;OAMG;IACG,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrG;;;;;OAKG;IACG,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIjG;;;;OAIG;IACH,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMhD;;;;;;;OAOG;IACG,YAAY,CACjB,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAM7B;;;;;;OAMG;IACG,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAI3E,6BAA6B;YAqB7B,kCAAkC;YA0ClC,UAAU;CAcxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAyC,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ9E,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAyC,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ9E,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAE9F,qBAAa,MAAM;IAOC,MAAM,EAAE,WAAW;IANtC,QAAQ,EAAE,MAAM,CAAO;IACvB,iBAAiB,SAAK;IACtB,aAAa,UAAS;IACtB,QAAQ,UAAS;IACjB,UAAU,EAAE,UAAU,CAAC;gBAEJ,MAAM,EAAE,WAAW;IAQhC,UAAU,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;IA0DrE,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;IAuCvB,6BAA6B,CAAC,eAAe,SAAS,cAAc,EACzE,WAAW,EAAE,wBAAwB,GACnC,OAAO,CAAC,eAAe,CAAC;IA+FrB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuDjG,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;CAGrB"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './config.js';
|
|
|
3
3
|
export { ClientResponse } from './interactions/customerInteraction.js';
|
|
4
4
|
export { AccountBalanceResponse } from './interactions/balanceInteraction.js';
|
|
5
5
|
export { StatementResponse } from './interactions/statementInteraction.js';
|
|
6
|
+
export { PortfolioResponse } from './interactions/portfolioInteraction.js';
|
|
6
7
|
export * from './segment.js';
|
|
7
8
|
export * from './message.js';
|
|
8
9
|
export * from './dialog.js';
|
|
@@ -14,4 +15,5 @@ export * from './accountBalance.js';
|
|
|
14
15
|
export * from './bpd.js';
|
|
15
16
|
export * from './upd.js';
|
|
16
17
|
export * from './mt940parser.js';
|
|
18
|
+
export * from './mt535parser.js';
|
|
17
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ClientResponse, CustomerOrderInteraction } from './customerInteraction.js';
|
|
2
|
+
import { FinTSConfig } from '../config.js';
|
|
3
|
+
import { Message } from '../message.js';
|
|
4
|
+
import { Segment } from '../segment.js';
|
|
5
|
+
import { StatementOfHoldings, Holding } from '../mt535parser.js';
|
|
6
|
+
/**
|
|
7
|
+
* Represents a single holding within a stock portfolio.
|
|
8
|
+
* This is an alias for the Holding interface from the MT535 parser.
|
|
9
|
+
*/
|
|
10
|
+
export type PortfolioHolding = Holding;
|
|
11
|
+
/**
|
|
12
|
+
* Represents the structured portfolio data parsed from an MT535 message.
|
|
13
|
+
* This is an alias for the StatementOfHoldings interface from the MT535 parser.
|
|
14
|
+
*/
|
|
15
|
+
export type ParsedPortfolioStatement = StatementOfHoldings;
|
|
16
|
+
export interface PortfolioResponse extends ClientResponse {
|
|
17
|
+
/**
|
|
18
|
+
* The parsed portfolio statement containing holdings and total value
|
|
19
|
+
*/
|
|
20
|
+
portfolioStatement?: ParsedPortfolioStatement;
|
|
21
|
+
/**
|
|
22
|
+
* Raw MT535 data if parsing fails
|
|
23
|
+
*/
|
|
24
|
+
rawMT535Data?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Interaction for requesting and parsing stock portfolio information (HKWPD/HIWPD)
|
|
28
|
+
*/
|
|
29
|
+
export declare class PortfolioInteraction extends CustomerOrderInteraction {
|
|
30
|
+
accountNumber: string;
|
|
31
|
+
private currency?;
|
|
32
|
+
private priceQuality?;
|
|
33
|
+
private maxEntries?;
|
|
34
|
+
private paginationMarker?;
|
|
35
|
+
constructor(accountNumber: string, currency?: string | undefined, priceQuality?: "1" | "2" | undefined, maxEntries?: number | undefined, paginationMarker?: string | undefined);
|
|
36
|
+
createSegments(config: FinTSConfig): Segment[];
|
|
37
|
+
handleResponse(response: Message, clientResponse: PortfolioResponse): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=portfolioInteraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolioInteraction.d.ts","sourceRoot":"","sources":["../../../src/interactions/portfolioInteraction.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,wBAAwB,EACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,EAAe,mBAAmB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE9E;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAE3D,MAAM,WAAW,iBAAkB,SAAQ,cAAc;IACvD;;OAEG;IACH,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;IAC9C;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,wBAAwB;IAEvD,aAAa,EAAE,MAAM;IAC5B,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,UAAU,CAAC;IACnB,OAAO,CAAC,gBAAgB,CAAC;gBAJlB,aAAa,EAAE,MAAM,EACpB,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,uBAAW,EACxB,UAAU,CAAC,oBAAQ,EACnB,gBAAgB,CAAC,oBAAQ;IAKnC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,EAAE;IA8B9C,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,iBAAiB,GAAG,IAAI;CAe3E"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface StatementOfHoldings {
|
|
2
|
+
totalValue?: number;
|
|
3
|
+
currency?: string;
|
|
4
|
+
holdings: Holding[];
|
|
5
|
+
}
|
|
6
|
+
export interface Holding {
|
|
7
|
+
isin?: string;
|
|
8
|
+
wkn?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
amount?: number;
|
|
11
|
+
price?: number;
|
|
12
|
+
currency?: string;
|
|
13
|
+
value?: number;
|
|
14
|
+
acquisitionPrice?: number;
|
|
15
|
+
date?: Date;
|
|
16
|
+
}
|
|
17
|
+
export declare enum TokenType535 {
|
|
18
|
+
DepotValueBlock = "DepotValueBlock",
|
|
19
|
+
DepotValueCurrency = "DepotValueCurrency",
|
|
20
|
+
FinBlock = "FinBlock",
|
|
21
|
+
SecurityIdentification = "SecurityIdentification",
|
|
22
|
+
AcquisitionPrice = "AcquisitionPrice",
|
|
23
|
+
PriceBlock = "PriceBlock",
|
|
24
|
+
AmountBlock = "AmountBlock",
|
|
25
|
+
DateTimeBlock = "DateTimeBlock",
|
|
26
|
+
DateString = "DateString",
|
|
27
|
+
TimeString = "TimeString"
|
|
28
|
+
}
|
|
29
|
+
export declare class Mt535Parser {
|
|
30
|
+
private rawData;
|
|
31
|
+
private cleanedRawData;
|
|
32
|
+
constructor(rawData: string);
|
|
33
|
+
parse(): StatementOfHoldings;
|
|
34
|
+
private parseDepotValue;
|
|
35
|
+
private parseHoldings;
|
|
36
|
+
private parseHolding;
|
|
37
|
+
private parseSecurityIdentification;
|
|
38
|
+
private parseAcquisitionPrice;
|
|
39
|
+
private parsePrice;
|
|
40
|
+
private parseAmount;
|
|
41
|
+
private parseDateTime;
|
|
42
|
+
private parseDate;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=mt535parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mt535parser.d.ts","sourceRoot":"","sources":["../../src/mt535parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,oBAAY,YAAY;IACtB,eAAe,oBAAoB;IACnC,kBAAkB,uBAAuB;IACzC,QAAQ,aAAa;IACrB,sBAAsB,2BAA2B;IACjD,gBAAgB,qBAAqB;IACrC,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,UAAU,eAAe;IACzB,UAAU,eAAe;CAC1B;AAgBD,qBAAa,WAAW;IAGV,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,cAAc,CAAS;gBAEX,OAAO,EAAE,MAAM;IAWnC,KAAK,IAAI,mBAAmB;IAc5B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,2BAA2B;IAyBnC,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,SAAS;CAgBlB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SegmentHeader } from '../segmentHeader.js';
|
|
2
|
+
import { Binary } from '../dataElements/Binary.js';
|
|
3
|
+
import { SegmentDefinition } from '../segmentDefinition.js';
|
|
4
|
+
export type HIWPDSegment = {
|
|
5
|
+
header: SegmentHeader;
|
|
6
|
+
/**
|
|
7
|
+
* Portfolio statement in S.W.I.F.T. format MT 535 or 571
|
|
8
|
+
*/
|
|
9
|
+
portfolioStatement: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Geschäftsvorfälle: C.4.3.1 Kreditinstitutsrückmeldung
|
|
13
|
+
* Version: 6
|
|
14
|
+
*/
|
|
15
|
+
export declare class HIWPD extends SegmentDefinition {
|
|
16
|
+
static Id: string;
|
|
17
|
+
static Version: number;
|
|
18
|
+
constructor();
|
|
19
|
+
version: number;
|
|
20
|
+
elements: Binary[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=HIWPD.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HIWPD.d.ts","sourceRoot":"","sources":["../../../src/segments/HIWPD.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB;;OAEG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,qBAAa,KAAM,SAAQ,iBAAiB;IAC3C,MAAM,CAAC,EAAE,SAAW;IACpB,MAAM,CAAC,OAAO,SAAK;;IAInB,OAAO,SAAiB;IACxB,QAAQ,WAA4C;CACpD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SegmentHeader } from '../segmentHeader.js';
|
|
2
|
+
import { Account, AccountGroup } from '../dataGroups/Account.js';
|
|
3
|
+
import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
|
|
4
|
+
import { Numeric } from '../dataElements/Numeric.js';
|
|
5
|
+
import { SegmentDefinition } from '../segmentDefinition.js';
|
|
6
|
+
export type HKWPDSegment = {
|
|
7
|
+
header: SegmentHeader;
|
|
8
|
+
/**
|
|
9
|
+
* Depot
|
|
10
|
+
*/
|
|
11
|
+
depot: Account;
|
|
12
|
+
/**
|
|
13
|
+
* Optional: Currency of the portfolio statement
|
|
14
|
+
*/
|
|
15
|
+
currency?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional: Price quality
|
|
18
|
+
* 1 = Current prices (Realtime)
|
|
19
|
+
* 2 = Delayed prices (Delayed)
|
|
20
|
+
*/
|
|
21
|
+
priceQuality?: '1' | '2';
|
|
22
|
+
/**
|
|
23
|
+
* Optional: Maximum number of entries
|
|
24
|
+
*/
|
|
25
|
+
maxEntries?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Pagination marker
|
|
28
|
+
* Optional: If a pagination marker was previously returned
|
|
29
|
+
*/
|
|
30
|
+
paginationMarker?: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Geschäftsvorfälle: C.4.3.1 Depotaufstellung
|
|
34
|
+
* Version: 6
|
|
35
|
+
*/
|
|
36
|
+
export declare class HKWPD extends SegmentDefinition {
|
|
37
|
+
static Id: string;
|
|
38
|
+
static Version: number;
|
|
39
|
+
constructor();
|
|
40
|
+
version: number;
|
|
41
|
+
elements: (AlphaNumeric | AccountGroup | Numeric)[];
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=HKWPD.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HKWPD.d.ts","sourceRoot":"","sources":["../../../src/segments/HKWPD.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,qBAAa,KAAM,SAAQ,iBAAiB;IAC3C,MAAM,CAAC,EAAE,SAAW;IACpB,MAAM,CAAC,OAAO,SAAK;;IAInB,OAAO,SAAiB;IACxB,QAAQ,4CAMN;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/segments/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/segments/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAqC5D,wBAAgB,gBAAgB,SAkC/B;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,GACT,iBAAiB,GAAG,SAAS,CAE/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HIWPD.test.d.ts","sourceRoot":"","sources":["../../../src/tests/HIWPD.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HKWPD.test.d.ts","sourceRoot":"","sources":["../../../src/tests/HKWPD.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mt535parser.test.d.ts","sourceRoot":"","sources":["../../../src/tests/mt535parser.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lib-fints",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Typescript/Javascript client library for Online-Banking via the FinTS 3.0 protocol with PIN/TAN",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "rm -rf ./dist && tsc",
|
|
24
|
+
"pack": "npm run build && npm pack --pack-destination ~/npm-repo",
|
|
25
|
+
"test": "vitest"
|
|
26
|
+
},
|
|
22
27
|
"keywords": [
|
|
23
28
|
"FinTS",
|
|
24
29
|
"HBCI",
|
|
@@ -36,10 +41,5 @@
|
|
|
36
41
|
"@types/node": "^20.10.6",
|
|
37
42
|
"typescript": "^5.3.3",
|
|
38
43
|
"vitest": "^1.6.0"
|
|
39
|
-
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"build": "rm -rf ./dist && tsc",
|
|
42
|
-
"pack": "npm run build && npm pack --pack-destination ~/npm-repo",
|
|
43
|
-
"test": "vitest"
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
}
|
package/dist/httpClientNode.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Message } from './message.js';
|
|
2
|
-
import * as https from 'https';
|
|
3
|
-
export class HttpClientNode {
|
|
4
|
-
url;
|
|
5
|
-
debug;
|
|
6
|
-
constructor(url, debug = false) {
|
|
7
|
-
this.url = url;
|
|
8
|
-
this.debug = debug;
|
|
9
|
-
}
|
|
10
|
-
async sendMessage(message) {
|
|
11
|
-
const encodedMessage = message.encode();
|
|
12
|
-
const requestBuffer = Buffer.from(encodedMessage).toString('base64');
|
|
13
|
-
if (this.debug) {
|
|
14
|
-
console.log('Request Message:\n' + message.toString());
|
|
15
|
-
}
|
|
16
|
-
const requestOptions = {
|
|
17
|
-
method: 'POST',
|
|
18
|
-
headers: { 'Content-Type': 'text/plain' },
|
|
19
|
-
};
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
const req = https.request(this.url, requestOptions, (res) => {
|
|
22
|
-
let data = '';
|
|
23
|
-
res.on('data', (chunk) => {
|
|
24
|
-
data += chunk;
|
|
25
|
-
});
|
|
26
|
-
res.on('end', () => {
|
|
27
|
-
if (res.statusCode === 200) {
|
|
28
|
-
const responseBuffer = Buffer.from(data, 'base64');
|
|
29
|
-
const responseText = responseBuffer.toString('latin1');
|
|
30
|
-
try {
|
|
31
|
-
const customerOrderMessage = message;
|
|
32
|
-
const responseMessage = Message.decode(responseText, customerOrderMessage.supportsPartedResponseSegments
|
|
33
|
-
? customerOrderMessage.orderResponseSegId
|
|
34
|
-
: undefined);
|
|
35
|
-
if (this.debug) {
|
|
36
|
-
console.log('Response Message:\n' + responseMessage.toString(true) + '\n');
|
|
37
|
-
}
|
|
38
|
-
resolve(responseMessage);
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
console.error('Error decoding response message:', error);
|
|
42
|
-
console.error('Response Message Content:\n', responseText.split("'").join('\n'));
|
|
43
|
-
reject(error);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
reject(new Error(`Request failed with status code ${res.statusCode}: ${data}`));
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
req.on('error', (error) => {
|
|
52
|
-
console.error('Request error:', error);
|
|
53
|
-
reject(error);
|
|
54
|
-
});
|
|
55
|
-
req.write(requestBuffer);
|
|
56
|
-
req.end();
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { CustomerMessage, Message } from './message.js';
|
|
2
|
-
export declare class HttpClientNode {
|
|
3
|
-
url: string;
|
|
4
|
-
debug: boolean;
|
|
5
|
-
constructor(url: string, debug?: boolean);
|
|
6
|
-
sendMessage(message: CustomerMessage): Promise<Message>;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=httpClientNode.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"httpClientNode.d.ts","sourceRoot":"","sources":["../../src/httpClientNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAwB,OAAO,EAAE,MAAM,cAAc,CAAC;AAG9E,qBAAa,cAAc;IACN,GAAG,EAAE,MAAM;IAAS,KAAK;gBAAzB,GAAG,EAAE,MAAM,EAAS,KAAK,UAAQ;IAE9C,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;CA2D9D"}
|