commit f2abaf6988b6f1da85508770b9d0851f1138b48f
parent b946e91782c06f323efd3cb7491fcd427fc9fbae
Author: Florian Dold <dold@taler.net>
Date: Mon, 24 Aug 2026 02:28:37 +0200
core bank client: update account and history types for API v12
Diffstat:
3 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
@@ -132,7 +132,7 @@ export enum TalerCoreBankCacheEviction {
* Uses libtool's current:revision:age versioning.
*/
export class TalerCoreBankHttpClient {
- public static readonly PROTOCOL_VERSION = "12:0:4";
+ public static readonly PROTOCOL_VERSION = "12:0:0";
httpLib: HttpRequestLibrary;
cacheEvictor: CacheEvictor<TalerCoreBankCacheEviction>;
@@ -692,6 +692,37 @@ export class TalerCoreBankHttpClient {
}
/**
+ * Read the full transaction history of an account that the bank has marked
+ * public. This deliberately sends no Authorization header. Private and
+ * unknown accounts are both reported as not found by Core Bank API v12.
+ */
+ async getPublicTransactions(
+ username: string,
+ params?: PaginationParams & LongPollParams,
+ ) {
+ const url = new URL(
+ `accounts/${pathSegment(username)}/transactions`,
+ this.baseUrl,
+ );
+ addPaginationParams(url, params);
+ addLongPollingParam(url, params);
+ const resp = await this.httpLib.fetch(url.href, { method: "GET" });
+ switch (resp.status) {
+ case HttpStatusCode.Ok:
+ return opSuccessFromHttp(
+ resp,
+ codecForBankAccountTransactionsResponse(),
+ );
+ case HttpStatusCode.NoContent:
+ return opFixedSuccess(resp, { transactions: [] });
+ case HttpStatusCode.NotFound:
+ return opKnownHttpFailure(resp.status, resp);
+ default:
+ return opUnknownHttpFailure(resp);
+ }
+ }
+
+ /**
* https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-transactions-$TRANSACTION_ID
*
*/
diff --git a/packages/taler-util/src/types-taler-corebank.ts b/packages/taler-util/src/types-taler-corebank.ts
@@ -325,6 +325,15 @@ export interface ChallengeContactData {
phone?: PhoneNumber;
}
+/**
+ * Sparse contact-data update used by account PATCH requests.
+ * Omitted members are preserved, while null explicitly removes a contact.
+ */
+export interface ChallengeContactDataPatch {
+ email?: EmailAddress | null;
+ phone?: PhoneNumber | null;
+}
+
export interface AccountReconfiguration {
// Addresses where to send the TAN for transactions.
// Currently only used for cashouts.
@@ -332,7 +341,7 @@ export interface AccountReconfiguration {
// In the future, might be used for other transactions
// as well.
// Only admin can change this property.
- contact_data?: ChallengeContactData;
+ contact_data?: ChallengeContactDataPatch;
// 'payto' URI of a fiat bank account.
// Payments will be sent to this bank account
@@ -357,10 +366,10 @@ export interface AccountReconfiguration {
// @since **v9**
conversion_rate_class_id?: Integer | null;
- // If present and not empty, enables 2FA and set the TAN channels used for challenges
- // Sending null or an empty array will disable 2FA
+ // If present and not empty, enables 2FA and sets the TAN channels used for
+ // challenges. An empty array disables 2FA.
// @since **v10**
- tan_channels?: TanChannel[] | null;
+ tan_channels?: TanChannel[];
}
export interface AccountPasswordChange {
@@ -615,8 +624,8 @@ export interface AccountData {
// @deprecated since **v7**
// is_locked?: boolean;
- // Is 2FA enabled and what channel is used for challenges?
- tan_channel?: TanChannel;
+ // Is 2FA enabled and which channels are used for challenges?
+ tan_channels?: TanChannel[];
// Current status of the account
// active: the account can be used
@@ -836,7 +845,12 @@ export const codecForCoreBankConfig = (): Codec<TalerCorebankConfigResponse> =>
),
),
)
- .property("wire_type", codecOptionalDefault(codecForString(), "iban") as unknown as Codec<string | undefined>)
+ .property(
+ "wire_type",
+ codecOptionalDefault(codecForString(), "iban") as unknown as Codec<
+ string | undefined
+ >,
+ )
.property("wire_transfer_fees", codecOptional(codecForAmountString()))
.property("min_wire_transfer_amount", codecOptional(codecForAmountString()))
.property("max_wire_transfer_amount", codecOptional(codecForAmountString()))
@@ -911,11 +925,13 @@ export const codecForAccountData = (): Codec<AccountData> =>
.property("is_taler_exchange", codecForBoolean())
.property("conversion_rate_class_id", codecOptional(codecForNumber()))
.property(
- "tan_channel",
+ "tan_channels",
codecOptional(
- codecForEither(
- codecForConstString(TanChannel.SMS),
- codecForConstString(TanChannel.EMAIL),
+ codecForList(
+ codecForEither(
+ codecForConstString(TanChannel.SMS),
+ codecForConstString(TanChannel.EMAIL),
+ ),
),
),
)
diff --git a/packages/web-util/src/context/bank-api.ts b/packages/web-util/src/context/bank-api.ts
@@ -109,7 +109,7 @@ export const BankApiProvider = ({
const config = await getRemoteConfig();
if (!active) return;
checkedFor.current = endpointKey;
- if (LibtoolVersion.compare(VERSION, config.version)) {
+ if (LibtoolVersion.isCompatible(VERSION, config.version)) {
setChecked({ type: "ok", config, hints: [] });
} else {
setChecked({