clearbank-sdk 1.0.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 (142) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +295 -0
  4. package/dist/cjs/core/config.js +25 -0
  5. package/dist/cjs/core/config.js.map +1 -0
  6. package/dist/cjs/core/crypto.js +110 -0
  7. package/dist/cjs/core/crypto.js.map +1 -0
  8. package/dist/cjs/core/http.js +191 -0
  9. package/dist/cjs/core/http.js.map +1 -0
  10. package/dist/cjs/core/index.js +14 -0
  11. package/dist/cjs/core/index.js.map +1 -0
  12. package/dist/cjs/core/retry.js +42 -0
  13. package/dist/cjs/core/retry.js.map +1 -0
  14. package/dist/cjs/domains/accounts/index.js +6 -0
  15. package/dist/cjs/domains/accounts/index.js.map +1 -0
  16. package/dist/cjs/domains/accounts/service.js +216 -0
  17. package/dist/cjs/domains/accounts/service.js.map +1 -0
  18. package/dist/cjs/domains/accounts/types.js +3 -0
  19. package/dist/cjs/domains/accounts/types.js.map +1 -0
  20. package/dist/cjs/domains/embedded/index.js +6 -0
  21. package/dist/cjs/domains/embedded/index.js.map +1 -0
  22. package/dist/cjs/domains/embedded/service.js +215 -0
  23. package/dist/cjs/domains/embedded/service.js.map +1 -0
  24. package/dist/cjs/domains/embedded/types.js +3 -0
  25. package/dist/cjs/domains/embedded/types.js.map +1 -0
  26. package/dist/cjs/domains/multicurrency/index.js +6 -0
  27. package/dist/cjs/domains/multicurrency/index.js.map +1 -0
  28. package/dist/cjs/domains/multicurrency/service.js +202 -0
  29. package/dist/cjs/domains/multicurrency/service.js.map +1 -0
  30. package/dist/cjs/domains/multicurrency/types.js +3 -0
  31. package/dist/cjs/domains/multicurrency/types.js.map +1 -0
  32. package/dist/cjs/domains/payments/index.js +6 -0
  33. package/dist/cjs/domains/payments/index.js.map +1 -0
  34. package/dist/cjs/domains/payments/service.js +255 -0
  35. package/dist/cjs/domains/payments/service.js.map +1 -0
  36. package/dist/cjs/domains/payments/types.js +3 -0
  37. package/dist/cjs/domains/payments/types.js.map +1 -0
  38. package/dist/cjs/domains/webhooks/index.js +7 -0
  39. package/dist/cjs/domains/webhooks/index.js.map +1 -0
  40. package/dist/cjs/domains/webhooks/service.js +173 -0
  41. package/dist/cjs/domains/webhooks/service.js.map +1 -0
  42. package/dist/cjs/domains/webhooks/types.js +8 -0
  43. package/dist/cjs/domains/webhooks/types.js.map +1 -0
  44. package/dist/cjs/index.js +73 -0
  45. package/dist/cjs/index.js.map +1 -0
  46. package/dist/cjs/types/index.js +45 -0
  47. package/dist/cjs/types/index.js.map +1 -0
  48. package/dist/cjs/utils/index.js +46 -0
  49. package/dist/cjs/utils/index.js.map +1 -0
  50. package/dist/esm/core/config.js +22 -0
  51. package/dist/esm/core/config.js.map +1 -0
  52. package/dist/esm/core/crypto.js +105 -0
  53. package/dist/esm/core/crypto.js.map +1 -0
  54. package/dist/esm/core/http.js +187 -0
  55. package/dist/esm/core/http.js.map +1 -0
  56. package/dist/esm/core/index.js +5 -0
  57. package/dist/esm/core/index.js.map +1 -0
  58. package/dist/esm/core/retry.js +39 -0
  59. package/dist/esm/core/retry.js.map +1 -0
  60. package/dist/esm/domains/accounts/index.js +2 -0
  61. package/dist/esm/domains/accounts/index.js.map +1 -0
  62. package/dist/esm/domains/accounts/service.js +212 -0
  63. package/dist/esm/domains/accounts/service.js.map +1 -0
  64. package/dist/esm/domains/accounts/types.js +2 -0
  65. package/dist/esm/domains/accounts/types.js.map +1 -0
  66. package/dist/esm/domains/embedded/index.js +2 -0
  67. package/dist/esm/domains/embedded/index.js.map +1 -0
  68. package/dist/esm/domains/embedded/service.js +211 -0
  69. package/dist/esm/domains/embedded/service.js.map +1 -0
  70. package/dist/esm/domains/embedded/types.js +2 -0
  71. package/dist/esm/domains/embedded/types.js.map +1 -0
  72. package/dist/esm/domains/multicurrency/index.js +2 -0
  73. package/dist/esm/domains/multicurrency/index.js.map +1 -0
  74. package/dist/esm/domains/multicurrency/service.js +198 -0
  75. package/dist/esm/domains/multicurrency/service.js.map +1 -0
  76. package/dist/esm/domains/multicurrency/types.js +2 -0
  77. package/dist/esm/domains/multicurrency/types.js.map +1 -0
  78. package/dist/esm/domains/payments/index.js +2 -0
  79. package/dist/esm/domains/payments/index.js.map +1 -0
  80. package/dist/esm/domains/payments/service.js +251 -0
  81. package/dist/esm/domains/payments/service.js.map +1 -0
  82. package/dist/esm/domains/payments/types.js +2 -0
  83. package/dist/esm/domains/payments/types.js.map +1 -0
  84. package/dist/esm/domains/webhooks/index.js +2 -0
  85. package/dist/esm/domains/webhooks/index.js.map +1 -0
  86. package/dist/esm/domains/webhooks/service.js +168 -0
  87. package/dist/esm/domains/webhooks/service.js.map +1 -0
  88. package/dist/esm/domains/webhooks/types.js +5 -0
  89. package/dist/esm/domains/webhooks/types.js.map +1 -0
  90. package/dist/esm/index.js +56 -0
  91. package/dist/esm/index.js.map +1 -0
  92. package/dist/esm/types/index.js +41 -0
  93. package/dist/esm/types/index.js.map +1 -0
  94. package/dist/esm/utils/index.js +35 -0
  95. package/dist/esm/utils/index.js.map +1 -0
  96. package/dist/types/core/config.d.ts +34 -0
  97. package/dist/types/core/config.d.ts.map +1 -0
  98. package/dist/types/core/crypto.d.ts +20 -0
  99. package/dist/types/core/crypto.d.ts.map +1 -0
  100. package/dist/types/core/http.d.ts +34 -0
  101. package/dist/types/core/http.d.ts.map +1 -0
  102. package/dist/types/core/index.d.ts +7 -0
  103. package/dist/types/core/index.d.ts.map +1 -0
  104. package/dist/types/core/retry.d.ts +14 -0
  105. package/dist/types/core/retry.d.ts.map +1 -0
  106. package/dist/types/domains/accounts/index.d.ts +3 -0
  107. package/dist/types/domains/accounts/index.d.ts.map +1 -0
  108. package/dist/types/domains/accounts/service.d.ts +61 -0
  109. package/dist/types/domains/accounts/service.d.ts.map +1 -0
  110. package/dist/types/domains/accounts/types.d.ts +90 -0
  111. package/dist/types/domains/accounts/types.d.ts.map +1 -0
  112. package/dist/types/domains/embedded/index.d.ts +3 -0
  113. package/dist/types/domains/embedded/index.d.ts.map +1 -0
  114. package/dist/types/domains/embedded/service.d.ts +63 -0
  115. package/dist/types/domains/embedded/service.d.ts.map +1 -0
  116. package/dist/types/domains/embedded/types.d.ts +148 -0
  117. package/dist/types/domains/embedded/types.d.ts.map +1 -0
  118. package/dist/types/domains/multicurrency/index.d.ts +3 -0
  119. package/dist/types/domains/multicurrency/index.d.ts.map +1 -0
  120. package/dist/types/domains/multicurrency/service.d.ts +50 -0
  121. package/dist/types/domains/multicurrency/service.d.ts.map +1 -0
  122. package/dist/types/domains/multicurrency/types.d.ts +84 -0
  123. package/dist/types/domains/multicurrency/types.d.ts.map +1 -0
  124. package/dist/types/domains/payments/index.d.ts +3 -0
  125. package/dist/types/domains/payments/index.d.ts.map +1 -0
  126. package/dist/types/domains/payments/service.d.ts +65 -0
  127. package/dist/types/domains/payments/service.d.ts.map +1 -0
  128. package/dist/types/domains/payments/types.d.ts +107 -0
  129. package/dist/types/domains/payments/types.d.ts.map +1 -0
  130. package/dist/types/domains/webhooks/index.d.ts +3 -0
  131. package/dist/types/domains/webhooks/index.d.ts.map +1 -0
  132. package/dist/types/domains/webhooks/service.d.ts +66 -0
  133. package/dist/types/domains/webhooks/service.d.ts.map +1 -0
  134. package/dist/types/domains/webhooks/types.d.ts +215 -0
  135. package/dist/types/domains/webhooks/types.d.ts.map +1 -0
  136. package/dist/types/index.d.ts +54 -0
  137. package/dist/types/index.d.ts.map +1 -0
  138. package/dist/types/types/index.d.ts +77 -0
  139. package/dist/types/types/index.d.ts.map +1 -0
  140. package/dist/types/utils/index.d.ts +22 -0
  141. package/dist/types/utils/index.d.ts.map +1 -0
  142. package/package.json +96 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * GBP Payments service.
3
+ *
4
+ * Covers: FPS (single + bulk), Internal Transfers, CHAPS, Bacs returns,
5
+ * Cheque Deposits, Confirmation of Payee, Cross-Border (deprecated), SEPA SCT UK.
6
+ */
7
+ export class PaymentsService {
8
+ constructor(http) {
9
+ this.http = http;
10
+ }
11
+ // ---------------------------------------------------------------------------
12
+ // Faster Payments (FPS)
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Sends a single Faster Payment.
16
+ *
17
+ * @remarks
18
+ * Limit: £1,000,000 per payment. Confirmation via `TransactionSettled` webhook.
19
+ * Set `enforceSendToScheme: true` to always route via FPS scheme (subject to
20
+ * Pay.UK APP scam reimbursement liability).
21
+ */
22
+ async sendFPS(params, opts) {
23
+ const body = buildFpsBody(params.accountId, [params.payment]);
24
+ await this.http.post('/v3/Payments/FPS', body, opts);
25
+ }
26
+ /** Sends multiple Faster Payments in one request. */
27
+ async sendFPSBulk(params, opts) {
28
+ const body = buildFpsBody(params.accountId, params.payments);
29
+ await this.http.post('/v3/Payments/FPS', body, opts);
30
+ }
31
+ // ---------------------------------------------------------------------------
32
+ // Internal Transfers
33
+ // ---------------------------------------------------------------------------
34
+ /** Transfers funds between ClearBank-held accounts (same institution). */
35
+ async sendInternalTransfer(params, opts) {
36
+ const body = omitUndefined({
37
+ debtorAccountId: params.debtorAccountId,
38
+ creditorAccountId: params.creditorAccountId,
39
+ amount: params.amount,
40
+ currencyCode: params.currency ?? 'GBP',
41
+ reference: params.reference,
42
+ endToEndId: params.endToEndId,
43
+ debtorVirtualAccountId: params.debtorVirtualAccountId,
44
+ creditorVirtualAccountId: params.creditorVirtualAccountId,
45
+ });
46
+ await this.http.post('/v3/Payments/Transfer', body, opts);
47
+ }
48
+ /** Sends multiple internal transfers in one request. */
49
+ async sendBulkInternalTransfer(params, opts) {
50
+ const body = {
51
+ transfers: params.map((p) => omitUndefined({
52
+ debtorAccountId: p.debtorAccountId,
53
+ creditorAccountId: p.creditorAccountId,
54
+ amount: p.amount,
55
+ currencyCode: p.currency ?? 'GBP',
56
+ reference: p.reference,
57
+ endToEndId: p.endToEndId,
58
+ debtorVirtualAccountId: p.debtorVirtualAccountId,
59
+ creditorVirtualAccountId: p.creditorVirtualAccountId,
60
+ })),
61
+ };
62
+ await this.http.post('/v3/Payments/Transfer/Bulk', body, opts);
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // CHAPS
66
+ // ---------------------------------------------------------------------------
67
+ /**
68
+ * Sends a CHAPS customer credit transfer (pacs.008).
69
+ *
70
+ * @remarks
71
+ * No upper limit. Same-day settlement during Bank of England RTGS hours.
72
+ * Requires structured ISO 20022 creditor address.
73
+ */
74
+ async sendCHAPS(params, opts) {
75
+ const body = buildChapsBody(params);
76
+ await this.http.post('/payments/chaps/v5/customer-payments', body, opts);
77
+ }
78
+ /** Returns a received CHAPS payment. */
79
+ async returnCHAPS(params, opts) {
80
+ const body = {
81
+ originalInstructionId: params.originalInstructionId,
82
+ debtorAccountId: params.debtorAccountId,
83
+ returnReasonCode: params.returnReasonCode,
84
+ instructedAmount: { amount: params.amount, currency: params.currency ?? 'GBP' },
85
+ };
86
+ await this.http.post('/payments/chaps/v5/return-payments', body, opts);
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Bacs
90
+ // ---------------------------------------------------------------------------
91
+ /** Returns a Bacs payment received on a real account. */
92
+ async returnBacs(accountId, params, opts) {
93
+ const body = { transactionId: params.transactionId, reasonCode: params.reasonCode };
94
+ await this.http.post(`/v1/Accounts/${accountId}/Transactions/Returns`, body, opts);
95
+ }
96
+ /** Returns a Bacs payment received on a virtual account. */
97
+ async returnVirtualBacs(accountId, virtualAccountId, params, opts) {
98
+ const body = { transactionId: params.transactionId, reasonCode: params.reasonCode };
99
+ await this.http.post(`/v1/Accounts/${accountId}/Virtual/${virtualAccountId}/Transactions/Returns`, body, opts);
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // Cheques (ICS)
103
+ // ---------------------------------------------------------------------------
104
+ /** Submits a cheque image deposit via the Image Clearing System (ICS). */
105
+ async submitChequeDeposit(params, opts) {
106
+ const body = omitUndefined({
107
+ accountId: params.accountId,
108
+ amount: params.amount,
109
+ currency: params.currency ?? 'GBP',
110
+ chequeImageFront: params.chequeImageFront,
111
+ chequeImageBack: params.chequeImageBack,
112
+ micrLine: params.micrLine,
113
+ payeeName: params.payeeName,
114
+ chequeNumber: params.chequeNumber,
115
+ });
116
+ await this.http.post('/payments/cheques/v1/submit-deposit', body, opts);
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Confirmation of Payee (CoP)
120
+ // ---------------------------------------------------------------------------
121
+ /**
122
+ * Sends an outbound CoP name verification request.
123
+ *
124
+ * @remarks
125
+ * Match results: MATC (full match), CLOSE (close match), NOMATCH, INAM (wrong account type),
126
+ * PANM (partial name match).
127
+ */
128
+ async checkCoP(params, opts) {
129
+ const body = omitUndefined({
130
+ accountName: params.accountName,
131
+ sortCode: params.sortCode,
132
+ accountNumber: params.accountNumber,
133
+ accountType: params.accountType ?? 'Personal',
134
+ secondaryReference: params.secondaryReference,
135
+ });
136
+ const res = await this.http.post('/v1/Cop/outbound/name-verification', body, opts);
137
+ return res.data;
138
+ }
139
+ /** Opts a real account out of inbound CoP name checks. */
140
+ async optOutAccountCoP(accountId, opts) {
141
+ await this.http.put(`/v1/Cop/opt/accounts/${accountId}`, { optOut: true }, opts);
142
+ }
143
+ /** Opts a virtual account out of inbound CoP name checks. */
144
+ async optOutVirtualAccountCoP(accountId, virtualAccountId, opts) {
145
+ await this.http.put(`/v1/Cop/opt/accounts/${accountId}/virtual/${virtualAccountId}`, { optOut: true }, opts);
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // GBP Cross-Border (deprecated)
149
+ // ---------------------------------------------------------------------------
150
+ /**
151
+ * Sends a GBP cross-border payment.
152
+ * @deprecated EOL 13 November 2026. Use `MultiCurrencyService.sendPayment()` instead.
153
+ */
154
+ async sendCrossBorder(params, opts) {
155
+ const body = omitUndefined({
156
+ accountId: params.accountId,
157
+ amount: params.amount,
158
+ currency: params.currency ?? 'GBP',
159
+ creditor: { name: params.creditorName, iban: params.creditorIban, bic: params.creditorBic },
160
+ remittanceInformation: params.remittanceInformation,
161
+ });
162
+ await this.http.post('/payments/cross-border-sterling/v3/payments', body, opts);
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // SEPA Credit Transfer UK
166
+ // ---------------------------------------------------------------------------
167
+ /** Sends a SEPA Credit Transfer UK euro payment. */
168
+ async sendSEPA(params, opts) {
169
+ const body = omitUndefined({
170
+ debtorAccountId: params.debtorAccountId,
171
+ instructedAmount: { amount: params.amount, currency: 'EUR' },
172
+ creditor: { name: params.creditorName, iban: params.creditorIban, bic: params.creditorBic },
173
+ remittanceInformation: params.remittanceInformation,
174
+ endToEndId: params.endToEndId,
175
+ instructionId: params.instructionId,
176
+ });
177
+ await this.http.post('/payments/sepa-credit-transfer/v2/customer-payments', body, opts);
178
+ }
179
+ /** Returns a received SEPA Credit Transfer UK payment. */
180
+ async returnSEPA(params, opts) {
181
+ const body = {
182
+ originalInstructionId: params.originalInstructionId,
183
+ debtorAccountId: params.debtorAccountId,
184
+ returnReasonCode: params.returnReasonCode,
185
+ instructedAmount: { amount: params.amount, currency: 'EUR' },
186
+ };
187
+ await this.http.post('/payments/sepa-credit-transfer/v2/return-payments', body, opts);
188
+ }
189
+ }
190
+ // ---------------------------------------------------------------------------
191
+ // Helpers
192
+ // ---------------------------------------------------------------------------
193
+ function buildFpsBody(accountId, payments) {
194
+ return {
195
+ accountId,
196
+ payments: payments.map((p) => omitUndefined({
197
+ amount: p.amount,
198
+ currencyCode: p.currency ?? 'GBP',
199
+ destination: {
200
+ sortCode: p.destinationSortCode,
201
+ accountNumber: p.destinationAccountNumber,
202
+ name: p.destinationAccountName,
203
+ },
204
+ paymentType: p.paymentType ?? 'SIP',
205
+ enforceSendToScheme: p.enforceSendToScheme ?? false,
206
+ reference: p.reference,
207
+ endToEndId: p.endToEndId,
208
+ })),
209
+ };
210
+ }
211
+ function buildChapsBody(p) {
212
+ const body = {
213
+ debtorAccountId: p.debtorAccountId,
214
+ instructedAmount: { amount: p.amount, currency: p.currency ?? 'GBP' },
215
+ creditor: {
216
+ name: p.creditorName,
217
+ account: { sortCode: p.creditorSortCode, accountNumber: p.creditorAccountNumber },
218
+ address: buildAddress(p.creditorAddress),
219
+ },
220
+ remittanceInformation: p.remittanceInformation,
221
+ };
222
+ if (p.endToEndId)
223
+ body['endToEndId'] = p.endToEndId;
224
+ if (p.instructionId)
225
+ body['instructionId'] = p.instructionId;
226
+ if (p.debtorName !== undefined || p.debtorAddress !== undefined) {
227
+ body['debtor'] = omitUndefined({
228
+ name: p.debtorName,
229
+ address: p.debtorAddress ? buildAddress(p.debtorAddress) : undefined,
230
+ });
231
+ }
232
+ return body;
233
+ }
234
+ function buildAddress(addr) {
235
+ const result = {};
236
+ if (addr['streetName'])
237
+ result['streetName'] = addr['streetName'];
238
+ if (addr['buildingNumber'])
239
+ result['buildingNumber'] = addr['buildingNumber'];
240
+ if (addr['postCode'])
241
+ result['postCode'] = addr['postCode'];
242
+ if (addr['townName'])
243
+ result['townName'] = addr['townName'];
244
+ if (addr['country'])
245
+ result['country'] = addr['country'];
246
+ return result;
247
+ }
248
+ function omitUndefined(obj) {
249
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
250
+ }
251
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../src/domains/payments/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/domains/payments/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { WebhooksService, buildAckBody } from './service.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/domains/webhooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,168 @@
1
+ import { verifySignature } from '../../core/crypto.js';
2
+ import { ClearBankError } from '../../types/index.js';
3
+ export { buildAckBody } from './types.js';
4
+ /**
5
+ * Webhook signature verification and typed event dispatch.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const webhooks = client.webhooks;
10
+ *
11
+ * app.post('/webhooks', async (req, res) => {
12
+ * const body = JSON.stringify(req.body);
13
+ * const isValid = await webhooks.verifySignature(body, req.headers['digitalsignature'], publicKeyPem);
14
+ * if (!isValid) return res.status(401).send('Invalid signature');
15
+ *
16
+ * await webhooks.dispatch(req.body, {
17
+ * TransactionSettled: async (event) => {
18
+ * await processPayment(event);
19
+ * },
20
+ * onUnknown: (envelope) => console.log('Unknown event:', envelope.Type),
21
+ * });
22
+ *
23
+ * res.json(webhooks.buildAck(req.body));
24
+ * });
25
+ * ```
26
+ */
27
+ export class WebhooksService {
28
+ /**
29
+ * Verifies a ClearBank `DigitalSignature` header using ClearBank's public key.
30
+ * Download the public key from Portal → Webhook Management.
31
+ *
32
+ * @param body Raw request body as a string (before JSON.parse).
33
+ * @param signature Value of the `DigitalSignature` header.
34
+ * @param publicKeyPem ClearBank RSA public key in PEM format.
35
+ */
36
+ async verifySignature(body, signature, publicKeyPem) {
37
+ return verifySignature(body, signature, publicKeyPem);
38
+ }
39
+ /**
40
+ * Parses and validates a raw webhook body into a typed envelope.
41
+ *
42
+ * @throws {ClearBankError} if the body is not valid JSON or is missing the Type field.
43
+ */
44
+ parseEnvelope(rawBody) {
45
+ let parsed;
46
+ if (typeof rawBody === 'string') {
47
+ try {
48
+ parsed = JSON.parse(rawBody);
49
+ }
50
+ catch {
51
+ throw new ClearBankError({
52
+ message: 'Webhook body is not valid JSON',
53
+ statusCode: null,
54
+ });
55
+ }
56
+ }
57
+ else {
58
+ parsed = rawBody;
59
+ }
60
+ if (!parsed || typeof parsed !== 'object') {
61
+ throw new ClearBankError({ message: 'Webhook body must be an object', statusCode: null });
62
+ }
63
+ const obj = parsed;
64
+ if (typeof obj['Type'] !== 'string' || !obj['Type']) {
65
+ throw new ClearBankError({
66
+ message: 'Webhook envelope missing Type field',
67
+ statusCode: null,
68
+ });
69
+ }
70
+ return {
71
+ Type: obj['Type'],
72
+ Version: typeof obj['Version'] === 'number' ? obj['Version'] : 0,
73
+ Nonce: typeof obj['Nonce'] === 'number' ? obj['Nonce'] : 0,
74
+ Payload: obj['Payload'] ?? {},
75
+ };
76
+ }
77
+ /**
78
+ * Parses the Payload of an envelope into a strongly-typed event object.
79
+ * Returns `null` for unknown event types (forward-compatible).
80
+ */
81
+ parseEvent(envelope, eventType) {
82
+ if (envelope.Type !== eventType)
83
+ return null;
84
+ return envelope.Payload;
85
+ }
86
+ /**
87
+ * Dispatches a webhook envelope to the appropriate handler.
88
+ *
89
+ * Only the handlers you provide are called — unhandled event types are silently
90
+ * ignored unless you provide `onUnknown`. This makes it easy to add handlers
91
+ * incrementally as you subscribe to more webhook event types.
92
+ *
93
+ * @param envelope Parsed webhook envelope (from `parseEnvelope`).
94
+ * @param handlers Object mapping event type names to handler functions.
95
+ */
96
+ async dispatch(envelope, handlers) {
97
+ const type = envelope.Type;
98
+ switch (type) {
99
+ case 'FITestEvent':
100
+ await handlers.FITestEvent?.(envelope.Payload, envelope);
101
+ break;
102
+ case 'TransactionSettled':
103
+ await handlers.TransactionSettled?.(envelope.Payload, envelope);
104
+ break;
105
+ case 'PaymentMessageAssessmentFailed':
106
+ await handlers.PaymentMessageAssessmentFailed?.(envelope.Payload, envelope);
107
+ break;
108
+ case 'PaymentMessageValidationFailed':
109
+ await handlers.PaymentMessageValidationFailed?.(envelope.Payload, envelope);
110
+ break;
111
+ case 'TransactionRejected':
112
+ await handlers.TransactionRejected?.(envelope.Payload, envelope);
113
+ break;
114
+ case 'FpsPaymentReturnCreated':
115
+ await handlers.FpsPaymentReturnCreated?.(envelope.Payload, envelope);
116
+ break;
117
+ case 'BacsPaymentCreated':
118
+ await handlers.BacsPaymentCreated?.(envelope.Payload, envelope);
119
+ break;
120
+ case 'BacsMandateCreated':
121
+ await handlers.BacsMandateCreated?.(envelope.Payload, envelope);
122
+ break;
123
+ case 'BacsMandateCancelled':
124
+ await handlers.BacsMandateCancelled?.(envelope.Payload, envelope);
125
+ break;
126
+ case 'BacsMandateMigrated':
127
+ await handlers.BacsMandateMigrated?.(envelope.Payload, envelope);
128
+ break;
129
+ case 'ChapsPaymentCreated':
130
+ await handlers.ChapsPaymentCreated?.(envelope.Payload, envelope);
131
+ break;
132
+ case 'ChapsReturnCreated':
133
+ await handlers.ChapsReturnCreated?.(envelope.Payload, envelope);
134
+ break;
135
+ case 'CopOutboundResponse':
136
+ await handlers.CopOutboundResponse?.(envelope.Payload, envelope);
137
+ break;
138
+ case 'MccyTransactionCreated':
139
+ await handlers.MccyTransactionCreated?.(envelope.Payload, envelope);
140
+ break;
141
+ case 'FxTradeCreated':
142
+ await handlers.FxTradeCreated?.(envelope.Payload, envelope);
143
+ break;
144
+ case 'FxTradeSettled':
145
+ await handlers.FxTradeSettled?.(envelope.Payload, envelope);
146
+ break;
147
+ case 'CustomerKycStatusChanged':
148
+ await handlers.CustomerKycStatusChanged?.(envelope.Payload, envelope);
149
+ break;
150
+ case 'EmbeddedAccountCreated':
151
+ await handlers.EmbeddedAccountCreated?.(envelope.Payload, envelope);
152
+ break;
153
+ case 'EmbeddedTransactionSettled':
154
+ await handlers.EmbeddedTransactionSettled?.(envelope.Payload, envelope);
155
+ break;
156
+ default:
157
+ await handlers.onUnknown?.(envelope);
158
+ }
159
+ }
160
+ /**
161
+ * Builds the JSON acknowledgement body to send in the webhook response.
162
+ * ClearBank uses the nonce to track delivered events.
163
+ */
164
+ buildAck(envelope) {
165
+ return { nonce: envelope.Nonce };
166
+ }
167
+ }
168
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../../src/domains/webhooks/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Returns the JSON body to send as the webhook acknowledgement. */
2
+ export function buildAckBody(envelope) {
3
+ return { nonce: envelope.Nonce };
4
+ }
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/domains/webhooks/types.ts"],"names":[],"mappings":"AAuCA,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,QAAyB;IACpD,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * clearbank-sdk — Production-grade TypeScript SDK for the ClearBank UK API.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import { HttpClient } from './core/http.js';
7
+ import { resolveConfig } from './core/config.js';
8
+ import { AccountsService } from './domains/accounts/service.js';
9
+ import { PaymentsService } from './domains/payments/service.js';
10
+ import { MultiCurrencyService } from './domains/multicurrency/service.js';
11
+ import { EmbeddedBankingService } from './domains/embedded/service.js';
12
+ import { WebhooksService } from './domains/webhooks/service.js';
13
+ export { ClearBankError } from './types/index.js';
14
+ // Domain services
15
+ export { AccountsService } from './domains/accounts/service.js';
16
+ export { PaymentsService } from './domains/payments/service.js';
17
+ export { MultiCurrencyService } from './domains/multicurrency/service.js';
18
+ export { EmbeddedBankingService } from './domains/embedded/service.js';
19
+ export { WebhooksService } from './domains/webhooks/service.js';
20
+ export { buildAckBody } from './domains/webhooks/service.js';
21
+ // Utilities
22
+ export { generateUUID, isUUID, isValidSortCode, isValidAccountNumber, isValidIBAN, formatAmount, } from './utils/index.js';
23
+ // ---------------------------------------------------------------------------
24
+ // ClearBankClient
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * The top-level ClearBank API client.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const client = new ClearBankClient({
32
+ * apiToken: process.env.CLEARBANK_API_TOKEN!,
33
+ * privateKey: process.env.CLEARBANK_PRIVATE_KEY!,
34
+ * environment: 'simulation',
35
+ * });
36
+ *
37
+ * const accounts = await client.accounts.list();
38
+ * await client.payments.sendFPS({ accountId, payment: { ... } });
39
+ * ```
40
+ */
41
+ export class ClearBankClient {
42
+ constructor(config) {
43
+ const resolved = resolveConfig(config);
44
+ const http = new HttpClient(resolved);
45
+ this.accounts = new AccountsService(http);
46
+ this.payments = new PaymentsService(http);
47
+ this.multiCurrency = new MultiCurrencyService(http);
48
+ this.embedded = new EmbeddedBankingService(http);
49
+ this.webhooks = new WebhooksService();
50
+ }
51
+ static generateRequestId() {
52
+ return HttpClient.generateRequestId();
53
+ }
54
+ }
55
+ export default ClearBankClient;
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAMhE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAgBlD,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAkBhE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAoBhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAgB1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AA0BvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6B7D,YAAY;AACZ,OAAO,EACL,YAAY,EACZ,MAAM,EACN,eAAe,EACf,oBAAoB,EACpB,WAAW,EACX,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,eAAe;IAO1B,YAAY,MAAuB;QACjC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEtC,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,iBAAiB;QACtB,OAAO,UAAU,CAAC,iBAAiB,EAAE,CAAC;IACxC,CAAC;CACF;AAED,eAAe,eAAe,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Core types shared across the ClearBank SDK.
3
+ */
4
+ export class ClearBankError extends Error {
5
+ constructor(params) {
6
+ super(params.message);
7
+ this.name = 'ClearBankError';
8
+ this.statusCode = params.statusCode ?? null;
9
+ this.code = params.code ?? null;
10
+ this.correlationId = params.correlationId ?? null;
11
+ this.requestId = params.requestId ?? null;
12
+ this.details = params.details ?? null;
13
+ this.retryAfterSeconds = params.retryAfterSeconds ?? null;
14
+ // Maintain proper prototype chain
15
+ Object.setPrototypeOf(this, ClearBankError.prototype);
16
+ }
17
+ isNotFound() {
18
+ return this.statusCode === 404;
19
+ }
20
+ isConflict() {
21
+ return this.statusCode === 409;
22
+ }
23
+ isRateLimited() {
24
+ return this.statusCode === 429;
25
+ }
26
+ isUnprocessable() {
27
+ return this.statusCode === 422;
28
+ }
29
+ isRetryable() {
30
+ return this.statusCode === 429 || this.statusCode === 500 || this.statusCode === 503;
31
+ }
32
+ toString() {
33
+ let msg = `ClearBankError [${this.statusCode ?? 'network'}]: ${this.message}`;
34
+ if (this.correlationId)
35
+ msg += ` (X-Correlation-Id: ${this.correlationId})`;
36
+ if (this.retryAfterSeconds)
37
+ msg += ` (retry after ${this.retryAfterSeconds}s)`;
38
+ return msg;
39
+ }
40
+ }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAQvC,YAAY,MAQX;QACC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;QACtC,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAC;QAC1D,kCAAkC;QAClC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;IACjC,CAAC;IACD,UAAU;QACR,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;IACjC,CAAC;IACD,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;IACjC,CAAC;IACD,eAAe;QACb,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;IACjC,CAAC;IACD,WAAW;QACT,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC;IACvF,CAAC;IAEQ,QAAQ;QACf,IAAI,GAAG,GAAG,mBAAmB,IAAI,CAAC,UAAU,IAAI,SAAS,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAC9E,IAAI,IAAI,CAAC,aAAa;YAAE,GAAG,IAAI,uBAAuB,IAAI,CAAC,aAAa,GAAG,CAAC;QAC5E,IAAI,IAAI,CAAC,iBAAiB;YAAE,GAAG,IAAI,iBAAiB,IAAI,CAAC,iBAAiB,IAAI,CAAC;QAC/E,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ export { generateUUID } from '../core/crypto.js';
2
+ export { HttpClient } from '../core/http.js';
3
+ /** Returns true if a given string is a valid UUID v4 format. */
4
+ export function isUUID(value) {
5
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
6
+ }
7
+ /** Returns true if a string looks like a UK sort code (6 digits). */
8
+ export function isValidSortCode(value) {
9
+ return /^\d{6}$/.test(value);
10
+ }
11
+ /** Returns true if a string looks like a UK account number (8 digits). */
12
+ export function isValidAccountNumber(value) {
13
+ return /^\d{8}$/.test(value);
14
+ }
15
+ /** Returns true if a string looks like a valid IBAN. */
16
+ export function isValidIBAN(value) {
17
+ return /^[A-Z]{2}\d{2}[A-Z0-9]{1,30}$/.test(value);
18
+ }
19
+ /**
20
+ * Formats a decimal amount string for display.
21
+ *
22
+ * @example formatAmount('1234.5', 'GBP') // '£1,234.50'
23
+ */
24
+ export function formatAmount(amount, currency, locale = 'en-GB') {
25
+ const num = parseFloat(amount);
26
+ if (isNaN(num))
27
+ return amount;
28
+ return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(num);
29
+ }
30
+ /**
31
+ * Generates a pre-flight X-Request-Id for idempotent retries.
32
+ * Store this before sending — use the same ID when retrying on 5XX.
33
+ */
34
+ export { HttpClient as _HttpClient } from '../core/http.js';
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,gEAAgE;AAChE,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,wEAAwE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9F,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,QAAgB,EAAE,MAAM,GAAG,OAAO;IAC7E,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { TelemetryHook } from '../types/index.js';
2
+ export type Environment = 'simulation' | 'production';
3
+ export interface ClearBankConfig {
4
+ /** ClearBank API bearer token from the Portal. Required. */
5
+ readonly apiToken: string;
6
+ /** RSA private key as PEM string. Required for POST/PUT/PATCH requests. */
7
+ readonly privateKey?: string;
8
+ /** API environment. Defaults to 'simulation'. */
9
+ readonly environment?: Environment;
10
+ /** Override base URL — useful for testing. */
11
+ readonly baseUrl?: string;
12
+ /** HTTP timeout in ms. Defaults to 30000. */
13
+ readonly timeoutMs?: number;
14
+ /** Max retry attempts for retryable errors. Defaults to 3. */
15
+ readonly maxRetries?: number;
16
+ /** Base delay for exponential backoff in ms. Defaults to 1000. */
17
+ readonly retryBaseDelayMs?: number;
18
+ /** Max backoff delay cap in ms. Defaults to 30000. */
19
+ readonly retryMaxDelayMs?: number;
20
+ /** Observability hook called after every HTTP request. */
21
+ readonly telemetryHook?: TelemetryHook;
22
+ }
23
+ export interface ResolvedConfig {
24
+ readonly apiToken: string;
25
+ readonly privateKey: string | null;
26
+ readonly baseUrl: string;
27
+ readonly timeoutMs: number;
28
+ readonly maxRetries: number;
29
+ readonly retryBaseDelayMs: number;
30
+ readonly retryMaxDelayMs: number;
31
+ readonly telemetryHook: TelemetryHook | null;
32
+ }
33
+ export declare function resolveConfig(config: ClearBankConfig): ResolvedConfig;
34
+ //# sourceMappingURL=config.d.ts.map