diff options
Diffstat (limited to 'packages/taler-util/src/http-client')
-rw-r--r-- | packages/taler-util/src/http-client/authentication.ts | 8 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-conversion.ts | 36 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-core.ts | 204 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-integration.ts | 47 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-revenue.ts | 38 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/bank-wire.ts | 80 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/exchange.ts | 31 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/merchant.ts | 2 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/types.ts | 124 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/utils.ts | 12 |
10 files changed, 276 insertions, 306 deletions
diff --git a/packages/taler-util/src/http-client/authentication.ts b/packages/taler-util/src/http-client/authentication.ts index b27a266e9..66e00ded5 100644 --- a/packages/taler-util/src/http-client/authentication.ts +++ b/packages/taler-util/src/http-client/authentication.ts @@ -17,7 +17,7 @@ import { HttpStatusCode } from "../http-status-codes.js"; import { HttpRequestLibrary, createPlatformHttpLib, makeBasicAuthHeader } from "../http.js"; import { LibtoolVersion } from "../libtool-version.js"; -import { opEmptySuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { opEmptySuccess, opKnownHttpFailure, opSuccess, opUnknownFailure } from "../operation.js"; import { AccessToken, TalerAuthentication, codecForTokenSuccessResponse } from "./types.js"; import { makeBearerTokenAuthHeader } from "./utils.js"; @@ -59,8 +59,8 @@ export class TalerAuthenticationHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForTokenSuccessResponse()) //FIXME: missing in docs - case HttpStatusCode.Unauthorized: return opKnownFailure("wrong-credentials", resp) - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp) + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) default: return opUnknownFailure(resp, await resp.text()) } } @@ -76,7 +76,7 @@ export class TalerAuthenticationHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opEmptySuccess() //FIXME: missing in docs - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/bank-conversion.ts b/packages/taler-util/src/http-client/bank-conversion.ts index 2bc9fdb79..3ecb036ee 100644 --- a/packages/taler-util/src/http-client/bank-conversion.ts +++ b/packages/taler-util/src/http-client/bank-conversion.ts @@ -2,13 +2,13 @@ import { AmountJson, Amounts } from "../amounts.js"; import { HttpRequestLibrary } from "../http-common.js"; import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; -import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { LibtoolVersion } from "../libtool-version.js"; +import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opKnownHttpFailure, opSuccess, opUnknownFailure } from "../operation.js"; import { TalerErrorCode } from "../taler-error-codes.js"; import { codecForTalerErrorDetail } from "../wallet-types.js"; import { AccessToken, TalerBankConversionApi, - UserAndToken, codecForCashinConversionResponse, codecForCashoutConversionResponse, codecForConversionBankConfig @@ -22,6 +22,8 @@ export type TalerBankConversionErrorsByMethod<prop extends keyof TalerBankConver * The API is used by the wallets. */ export class TalerBankConversionHttpClient { + public readonly PROTOCOL_VERSION = "0:0:0"; + httpLib: HttpRequestLibrary; constructor( @@ -31,6 +33,11 @@ export class TalerBankConversionHttpClient { this.httpLib = httpClient ?? createPlatformHttpLib(); } + isCompatible(version: string): boolean { + const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version) + return compare?.compatible ?? false + } + /** * https://docs.taler.net/core/api-bank-conversion-info.html#get--config * @@ -42,6 +49,7 @@ export class TalerBankConversionHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForConversionBankConfig()) + case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp) default: return opUnknownFailure(resp, await resp.text()) } } @@ -67,14 +75,14 @@ export class TalerBankConversionHttpClient { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) switch (details.code) { - case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownFailure("missing-params", resp); - case TalerErrorCode.GENERIC_PARAMETER_MALFORMED: return opKnownFailure("wrong-calculation", resp); - case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownFailure("wrong-currency", resp); + case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownHttpFailure(resp.status, resp); + case TalerErrorCode.GENERIC_PARAMETER_MALFORMED: return opKnownHttpFailure(resp.status, resp); + case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, body) } } - case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp); - case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -100,14 +108,14 @@ export class TalerBankConversionHttpClient { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) switch (details.code) { - case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownFailure("missing-params", resp); - case TalerErrorCode.GENERIC_PARAMETER_MALFORMED: return opKnownFailure("wrong-calculation", resp); - case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownFailure("wrong-currency", resp); + case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownHttpFailure(resp.status, resp); + case TalerErrorCode.GENERIC_PARAMETER_MALFORMED: return opKnownHttpFailure(resp.status, resp); + case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, body) } } - case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp); - case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -127,8 +135,8 @@ export class TalerBankConversionHttpClient { }); switch (resp.status) { case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts index dbb6c7112..8a3283d0f 100644 --- a/packages/taler-util/src/http-client/bank-core.ts +++ b/packages/taler-util/src/http-client/bank-core.ts @@ -17,6 +17,7 @@ import { HttpStatusCode, LibtoolVersion, + LongPollParams, TalerErrorCode, codecForChallenge, codecForTalerErrorDetail, @@ -29,22 +30,26 @@ import { HttpRequestLibrary, createPlatformHttpLib } from "@gnu-taler/taler-util/http"; -import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opSuccess, opUnknownFailure } from "../operation.js"; import { TalerAuthenticationHttpClient } from "./authentication.js"; import { TalerBankConversionHttpClient } from "./bank-conversion.js"; import { TalerBankIntegrationHttpClient } from "./bank-integration.js"; import { TalerRevenueHttpClient } from "./bank-revenue.js"; import { TalerWireGatewayHttpClient } from "./bank-wire.js"; import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, WithdrawalOperationStatus, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashoutPending, codecForCashoutStatusResponse, codecForCashouts, codecForCoreBankConfig, codecForCreateTransactionResponse, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse, codecForRegisterAccountResponse, codecForWithdrawalPublicInfo } from "./types.js"; -import { addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js"; +import { addLongPollingParam, addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js"; export type TalerCoreBankResultByMethod<prop extends keyof TalerCoreBankHttpClient> = ResultByMethod<TalerCoreBankHttpClient, prop> export type TalerCoreBankErrorsByMethod<prop extends keyof TalerCoreBankHttpClient> = FailCasesByMethod<TalerCoreBankHttpClient, prop> /** - * Protocol version spoken with the bank. + * Protocol version spoken with the core bank. * + * Endpoint must be ordered in the same way that in the docs + * Response code (http and taler) must have the same order that in the docs + * That way is easier to see changes + * * Uses libtool's current:revision:age versioning. */ export class TalerCoreBankHttpClient { @@ -134,8 +139,8 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) @@ -166,17 +171,17 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) switch (details.code) { case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp); case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_NON_ADMIN_PATCH_CONTACT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return opKnownTalerFailure(details.code, resp); case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_MISSING_TAN_INFO: return opKnownTalerFailure(details.code, resp); default: return opUnknownFailure(resp, body) } } @@ -289,9 +294,10 @@ export class TalerCoreBankHttpClient { * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-transactions * */ - async getTransactions(auth: UserAndToken, pagination?: PaginationParams) { + async getTransactions(auth: UserAndToken, params?: PaginationParams & LongPollParams) { const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl); - addPaginationParams(url, pagination) + addPaginationParams(url, params) + addLongPollingParam(url, params) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { @@ -342,8 +348,8 @@ export class TalerCoreBankHttpClient { body, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.Ok: return opSuccess(resp, codecForCreateTransactionResponse()) + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); @@ -382,62 +388,63 @@ export class TalerCoreBankHttpClient { case HttpStatusCode.Ok: return opSuccess(resp, codecForBankAccountCreateWithdrawalResponse()) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + //FIXME: missing in docs case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-abort + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-confirm * */ - async abortWithdrawalById(auth: UserAndToken, wid: string) { - const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/abort`, this.baseUrl); + async confirmWithdrawalById(auth: UserAndToken, wid: string, cid?: string) { + const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/confirm`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) + Authorization: makeBearerTokenAuthHeader(auth.token), + "X-Challenge-Id": cid, }, }); switch (resp.status) { + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() //FIXME: missing in docs case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) - case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: { + const body = await resp.json() + const details = codecForTalerErrorDetail().decode(body) + switch (details.code) { + case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); + default: return opUnknownFailure(resp, body) + } + } default: return opUnknownFailure(resp, await resp.text()) } } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-confirm + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-abort * */ - async confirmWithdrawalById(auth: UserAndToken, wid: string, cid?: string) { - const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/confirm`, this.baseUrl); + async abortWithdrawalById(auth: UserAndToken, wid: string) { + const url = new URL(`accounts/${auth.username}/withdrawals/${wid}/abort`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { - Authorization: makeBearerTokenAuthHeader(auth.token), - "X-Challenge-Id": cid, + Authorization: makeBearerTokenAuthHeader(auth.token) }, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NoContent: return opEmptySuccess() //FIXME: missing in docs case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) - case HttpStatusCode.Conflict: { - const body = await resp.json() - const details = codecForTalerErrorDetail().decode(body) - switch (details.code) { - case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); - default: return opUnknownFailure(resp, body) - } - } + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -446,14 +453,13 @@ export class TalerCoreBankHttpClient { * https://docs.taler.net/core/api-corebank.html#get--withdrawals-$WITHDRAWAL_ID * */ - async getWithdrawalById(wid: string, wait?: { + async getWithdrawalById(wid: string, params?: { old_state?: WithdrawalOperationStatus, - timeoutMs: number - }) { + } & LongPollParams) { const url = new URL(`withdrawals/${wid}`, this.baseUrl); - if (wait) { - url.searchParams.set("long_poll_ms", String(wait.timeoutMs)) - url.searchParams.set("old_state", !wait.old_state ? "pending" : wait.old_state) + addLongPollingParam(url, params) + if (params) { + url.searchParams.set("old_state", !params.old_state ? "pending" : params.old_state) } const resp = await this.httpLib.fetch(url.href, { method: "GET", @@ -486,8 +492,8 @@ export class TalerCoreBankHttpClient { body, }); switch (resp.status) { - case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutPending()) + case HttpStatusCode.Accepted: return opKnownAlternativeFailure(resp, resp.status, codecForChallenge()) case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.Conflict: { const body = await resp.json() @@ -514,61 +520,6 @@ export class TalerCoreBankHttpClient { } /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-abort - * @deprecated since 4 - */ - async abortCashoutById(auth: UserAndToken, cid: number) { - const url = new URL(`accounts/${auth.username}/cashouts/${cid}/abort`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) - }, - }); - switch (resp.status) { - case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - /** - * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-confirm - * @deprecated since 4 - */ - async confirmCashoutById(auth: UserAndToken, cid: number, body: TalerCorebankApi.CashoutConfirmRequest) { - const url = new URL(`accounts/${auth.username}/cashouts/${cid}/confirm`, this.baseUrl); - const resp = await this.httpLib.fetch(url.href, { - method: "POST", - headers: { - Authorization: makeBearerTokenAuthHeader(auth.token) - }, - body, - }); - switch (resp.status) { - case HttpStatusCode.NoContent: return opEmptySuccess() - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Conflict: { - const body = await resp.json() - const details = codecForTalerErrorDetail().decode(body) - switch (details.code) { - case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownTalerFailure(details.code, resp); - case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownTalerFailure(details.code, resp); - default: return opUnknownFailure(resp, body) - } - } - case HttpStatusCode.TooManyRequests: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - /** * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts-$CASHOUT_ID * */ @@ -604,7 +555,6 @@ export class TalerCoreBankHttpClient { switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForCashouts()) case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] }); - case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp);; case HttpStatusCode.NotImplemented: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } @@ -632,41 +582,13 @@ export class TalerCoreBankHttpClient { } // - // MONITOR + // 2FA // /** - * https://docs.taler.net/core/api-corebank.html#get--monitor + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-challenge-$CHALLENGE_ID * */ - async getMonitor(auth: AccessToken, params: { timeframe?: TalerCorebankApi.MonitorTimeframeParam, which?: number } = {}) { - const url = new URL(`monitor`, this.baseUrl); - if (params.timeframe) { - url.searchParams.set("timeframe", TalerCorebankApi.MonitorTimeframeParam[params.timeframe]) - } - if (params.which) { - url.searchParams.set("which", String(params.which)) - } - const resp = await this.httpLib.fetch(url.href, { - method: "GET", - headers: { - Authorization: makeBearerTokenAuthHeader(auth) - }, - }); - switch (resp.status) { - case HttpStatusCode.Ok: return opSuccess(resp, codecForMonitorResponse()) - case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); - case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); - //FIXME remove when server is updated - //FIXME: should be 404 ? - case HttpStatusCode.ServiceUnavailable: return opKnownHttpFailure(resp.status, resp); - default: return opUnknownFailure(resp, await resp.text()) - } - } - - // - // 2FA - // async sendChallenge(auth: UserAndToken, cid: string) { const url = new URL(`accounts/${auth.username}/challenge/${cid}`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { @@ -691,6 +613,10 @@ export class TalerCoreBankHttpClient { } } + /** + * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-challenge-$CHALLENGE_ID-confirm + * + */ async confirmChallenge(auth: UserAndToken, cid: string, body: TalerCorebankApi.ChallengeSolve) { const url = new URL(`accounts/${auth.username}/challenge/${cid}/confirm`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { @@ -718,6 +644,36 @@ export class TalerCoreBankHttpClient { } } + // + // MONITOR + // + + /** + * https://docs.taler.net/core/api-corebank.html#get--monitor + * + */ + async getMonitor(auth: AccessToken, params: { timeframe?: TalerCorebankApi.MonitorTimeframeParam, which?: number } = {}) { + const url = new URL(`monitor`, this.baseUrl); + if (params.timeframe) { + url.searchParams.set("timeframe", TalerCorebankApi.MonitorTimeframeParam[params.timeframe]) + } + if (params.which) { + url.searchParams.set("which", String(params.which)) + } + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + headers: { + Authorization: makeBearerTokenAuthHeader(auth) + }, + }); + switch (resp.status) { + case HttpStatusCode.Ok: return opSuccess(resp, codecForMonitorResponse()) + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + default: return opUnknownFailure(resp, await resp.text()) + } + } + // // Others API diff --git a/packages/taler-util/src/http-client/bank-integration.ts b/packages/taler-util/src/http-client/bank-integration.ts index 757f1f897..2264b65bf 100644 --- a/packages/taler-util/src/http-client/bank-integration.ts +++ b/packages/taler-util/src/http-client/bank-integration.ts @@ -2,16 +2,18 @@ import { HttpRequestLibrary, readSuccessResponseJsonOrThrow } from "../http-comm import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; import { LibtoolVersion } from "../libtool-version.js"; -import { FailCasesByMethod, ResultByMethod, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opKnownHttpFailure, opKnownTalerFailure, opSuccess, opUnknownFailure } from "../operation.js"; import { TalerErrorCode } from "../taler-error-codes.js"; import { codecForTalerErrorDetail } from "../wallet-types.js"; import { + LongPollParams, TalerBankIntegrationApi, WithdrawalOperationStatus, codecForBankWithdrawalOperationPostResponse, codecForBankWithdrawalOperationStatus, codecForIntegrationBankConfig } from "./types.js"; +import { addLongPollingParam } from "./utils.js"; export type TalerBankIntegrationResultByMethod<prop extends keyof TalerBankIntegrationHttpClient> = ResultByMethod<TalerBankIntegrationHttpClient, prop> export type TalerBankIntegrationErrorsByMethod<prop extends keyof TalerBankIntegrationHttpClient> = FailCasesByMethod<TalerBankIntegrationHttpClient, prop> @@ -20,7 +22,7 @@ export type TalerBankIntegrationErrorsByMethod<prop extends keyof TalerBankInteg * The API is used by the wallets. */ export class TalerBankIntegrationHttpClient { - public readonly PROTOCOL_VERSION = "3:0:3"; + public readonly PROTOCOL_VERSION = "2:0:2"; httpLib: HttpRequestLibrary; @@ -55,21 +57,20 @@ export class TalerBankIntegrationHttpClient { * https://docs.taler.net/core/api-bank-integration.html#get--withdrawal-operation-$WITHDRAWAL_ID * */ - async getWithdrawalOperationById(woid: string, wait?: { - old_state?: WithdrawalOperationStatus, - timeoutMs: number - }) { + async getWithdrawalOperationById(woid: string, params?: { + old_state?: WithdrawalOperationStatus + } & LongPollParams) { const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl); - if (wait) { - url.searchParams.set("long_poll_ms", String(wait.timeoutMs)) - url.searchParams.set("old_state", !wait.old_state ? "pending" : wait.old_state) + addLongPollingParam(url, params) + if (params) { + url.searchParams.set("old_state", !params.old_state ? "pending" : params.old_state) } const resp = await this.httpLib.fetch(url.href, { method: "GET" }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForBankWithdrawalOperationStatus()) - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) default: return opUnknownFailure(resp, await resp.text()) } } @@ -86,15 +87,15 @@ export class TalerBankIntegrationHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForBankWithdrawalOperationPostResponse()) - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp) + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) case HttpStatusCode.Conflict: { const body = await resp.json() const details = codecForTalerErrorDetail().decode(body) switch (details.code) { - case TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT: return opKnownFailure("already-selected", resp); - case TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT: return opKnownFailure("duplicated-reserve-id", resp); - case TalerErrorCode.BANK_UNKNOWN_ACCOUNT: return opKnownFailure("account-not-found", resp); - case TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE: return opKnownFailure("account-not-exchange", resp); + case TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_UNKNOWN_ACCOUNT: return opKnownTalerFailure(details.code, resp); + case TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE: return opKnownTalerFailure(details.code, resp); default: return opUnknownFailure(resp, body) } } @@ -102,5 +103,21 @@ export class TalerBankIntegrationHttpClient { } } + /** + * https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid + * + */ + async abortWithdrawalOperationById(woid: string) { + const url = new URL(`withdrawal-operation/${woid}/abort`, this.baseUrl); + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + }); + switch (resp.status) { + case HttpStatusCode.NoContent: return opEmptySuccess() + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp) + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); + default: return opUnknownFailure(resp, await resp.text()) + } + } } diff --git a/packages/taler-util/src/http-client/bank-revenue.ts b/packages/taler-util/src/http-client/bank-revenue.ts index 040ad8dd2..9dfcc4f64 100644 --- a/packages/taler-util/src/http-client/bank-revenue.ts +++ b/packages/taler-util/src/http-client/bank-revenue.ts @@ -1,9 +1,9 @@ import { HttpRequestLibrary, makeBasicAuthHeader, readSuccessResponseJsonOrThrow } from "../http-common.js"; import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; -import { FailCasesByMethod, ResultByMethod, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; -import { PaginationParams, TalerRevenueApi, codecForMerchantIncomingHistory } from "./types.js"; -import { addPaginationParams } from "./utils.js"; +import { FailCasesByMethod, ResultByMethod, opKnownHttpFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { LongPollParams, PaginationParams, TalerRevenueApi, codecForMerchantIncomingHistory } from "./types.js"; +import { addLongPollingParam, addPaginationParams } from "./utils.js"; export type TalerBankRevenueResultByMethod<prop extends keyof TalerRevenueHttpClient> = ResultByMethod<TalerRevenueHttpClient, prop> export type TalerBankRevenueErrorsByMethod<prop extends keyof TalerRevenueHttpClient> = FailCasesByMethod<TalerRevenueHttpClient, prop> @@ -22,15 +22,37 @@ export class TalerRevenueHttpClient { ) { this.httpLib = httpClient ?? createPlatformHttpLib(); } + // public readonly PROTOCOL_VERSION = "4:0:0"; + // isCompatible(version: string): boolean { + // const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version) + // return compare?.compatible ?? false + // } + + // /** + // * https://docs.taler.net/core/api-corebank.html#config + // * + // */ + // async getConfig() { + // const url = new URL(`config`, this.baseUrl); + // const resp = await this.httpLib.fetch(url.href, { + // method: "GET" + // }); + // switch (resp.status) { + // case HttpStatusCode.Ok: return opSuccess(resp, codecForCoreBankConfig()) + // default: return opUnknownFailure(resp, await resp.text()) + // } + // } + /** * https://docs.taler.net/core/api-bank-revenue.html#get--history * * @returns */ - async getHistory(auth: string, pagination?: PaginationParams) { + async getHistory(auth: string, params?: PaginationParams & LongPollParams) { const url = new URL(`history`, this.baseUrl); - addPaginationParams(url, pagination) + addPaginationParams(url, params) + addLongPollingParam(url, params) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { @@ -39,9 +61,9 @@ export class TalerRevenueHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForMerchantIncomingHistory()) - case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("endpoint-wrong-or-username-wrong", resp); + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/bank-wire.ts b/packages/taler-util/src/http-client/bank-wire.ts index 7e3c00637..90c3aeae5 100644 --- a/packages/taler-util/src/http-client/bank-wire.ts +++ b/packages/taler-util/src/http-client/bank-wire.ts @@ -1,9 +1,9 @@ import { HttpRequestLibrary, makeBasicAuthHeader } from "../http-common.js"; import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; -import { FailCasesByMethod, ResultByMethod, opFixedSuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; -import { PaginationParams, TalerWireGatewayApi, codecForAddIncomingResponse, codecForIncomingHistory, codecForOutgoingHistory, codecForTransferResponse } from "./types.js"; -import { addPaginationParams } from "./utils.js"; +import { FailCasesByMethod, ResultByMethod, opFixedSuccess, opKnownHttpFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { LongPollParams, PaginationParams, TalerWireGatewayApi, codecForAddIncomingResponse, codecForIncomingHistory, codecForOutgoingHistory, codecForTransferResponse } from "./types.js"; +import { addLongPollingParam, addPaginationParams } from "./utils.js"; export type TalerWireGatewayResultByMethod<prop extends keyof TalerWireGatewayHttpClient> = ResultByMethod<TalerWireGatewayHttpClient, prop> export type TalerWireGatewayErrorsByMethod<prop extends keyof TalerWireGatewayHttpClient> = FailCasesByMethod<TalerWireGatewayHttpClient, prop> @@ -25,6 +25,27 @@ export class TalerWireGatewayHttpClient { ) { this.httpLib = httpClient ?? createPlatformHttpLib(); } + // public readonly PROTOCOL_VERSION = "4:0:0"; + // isCompatible(version: string): boolean { + // const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version) + // return compare?.compatible ?? false + // } + + // /** + // * https://docs.taler.net/core/api-corebank.html#config + // * + // */ + // async getConfig() { + // const url = new URL(`config`, this.baseUrl); + // const resp = await this.httpLib.fetch(url.href, { + // method: "GET" + // }); + // switch (resp.status) { + // case HttpStatusCode.Ok: return opSuccess(resp, codecForCoreBankConfig()) + // default: return opUnknownFailure(resp, await resp.text()) + // } + // } + /** * https://docs.taler.net/core/api-bank-wire.html#post--transfer @@ -42,10 +63,12 @@ export class TalerWireGatewayHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForTransferResponse()) - case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); - case HttpStatusCode.Conflict: return opKnownFailure("request-uid-already-used", resp); + //FIXME: show more details in docs + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + //FIXME: show more details in docs + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -54,9 +77,10 @@ export class TalerWireGatewayHttpClient { * https://docs.taler.net/core/api-bank-wire.html#get--history-incoming * */ - async getHistoryIncoming(auth: string, pagination?: PaginationParams) { + async getHistoryIncoming(auth: string, params?: PaginationParams & LongPollParams) { const url = new URL(`history/incoming`, this.baseUrl); - addPaginationParams(url, pagination) + addPaginationParams(url, params) + addLongPollingParam(url, params) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { @@ -65,22 +89,25 @@ export class TalerWireGatewayHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForIncomingHistory()) - case HttpStatusCode.NoContent: return opFixedSuccess({ incoming_transactions: [] }) - case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + //FIXME: account should not be returned or make it optional + case HttpStatusCode.NoContent: return opFixedSuccess({ incoming_transactions: [], credit_account: undefined }) + //FIXME: show more details in docs + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + //FIXME: show more details in docs + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } - // return readSuccessResponseJsonOrThrow(resp, codecForIncomingHistory()); } /** * https://docs.taler.net/core/api-bank-wire.html#get--history-outgoing * */ - async getHistoryOutgoing(auth: string, pagination?: PaginationParams) { + async getHistoryOutgoing(auth: string, params?: PaginationParams & LongPollParams) { const url = new URL(`history/outgoing`, this.baseUrl); - addPaginationParams(url, pagination) + addPaginationParams(url, params) + addLongPollingParam(url, params) const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { @@ -89,10 +116,13 @@ export class TalerWireGatewayHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForOutgoingHistory()) - case HttpStatusCode.NoContent: return opFixedSuccess({ outgoing_transactions: [] }) - case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); + //FIXME: account should not be returned or make it optional + case HttpStatusCode.NoContent: return opFixedSuccess({ outgoing_transactions: [], debit_account: undefined }) + //FIXME: show more details in docs + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + //FIXME: show more details in docs + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -112,10 +142,12 @@ export class TalerWireGatewayHttpClient { }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForAddIncomingResponse()) - case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp); - case HttpStatusCode.Conflict: return opKnownFailure("reserve-id-already-used", resp); + //FIXME: show more details in docs + case HttpStatusCode.BadRequest: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + //FIXME: show more details in docs + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/exchange.ts b/packages/taler-util/src/http-client/exchange.ts index f55be0043..36adb5a1a 100644 --- a/packages/taler-util/src/http-client/exchange.ts +++ b/packages/taler-util/src/http-client/exchange.ts @@ -3,7 +3,7 @@ import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; import { LibtoolVersion } from "../libtool-version.js"; import { hash } from "../nacl-fast.js"; -import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opKnownFailure, opSuccess, opUnknownFailure } from "../operation.js"; +import { FailCasesByMethod, ResultByMethod, opEmptySuccess, opFixedSuccess, opKnownHttpFailure, opSuccess, opUnknownFailure } from "../operation.js"; import { TalerSignaturePurpose, amountToBuffer, bufferForUint32, buildSigPS, decodeCrock, eddsaSign, encodeCrock, stringToBytes, timestampRoundedToBuffer } from "../taler-crypto.js"; import { OfficerAccount, PaginationParams, SigningKey, TalerExchangeApi, codecForAmlDecisionDetails, codecForAmlRecords, codecForExchangeConfig } from "./types.js"; import { addPaginationParams } from "./utils.js"; @@ -15,7 +15,7 @@ export type TalerExchangeErrorsByMethod<prop extends keyof TalerExchangeHttpClie */ export class TalerExchangeHttpClient { httpLib: HttpRequestLibrary; - public readonly PROTOCOL_VERSION = "17:0:0"; + public readonly PROTOCOL_VERSION = "18:0:1"; constructor( readonly baseUrl: string, @@ -43,6 +43,9 @@ export class TalerExchangeHttpClient { } } + // TERMS + + // // AML operations // @@ -66,10 +69,10 @@ export class TalerExchangeHttpClient { case HttpStatusCode.Ok: return opSuccess(resp, codecForAmlRecords()) case HttpStatusCode.NoContent: return opFixedSuccess({ records: [] }) //this should be unauthorized - case HttpStatusCode.Forbidden: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("officer-not-found", resp); - case HttpStatusCode.Conflict: return opKnownFailure("officer-disabled", resp); + case HttpStatusCode.Forbidden: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -92,10 +95,10 @@ export class TalerExchangeHttpClient { case HttpStatusCode.Ok: return opSuccess(resp, codecForAmlDecisionDetails()) case HttpStatusCode.NoContent: return opFixedSuccess({ aml_history: [], kyc_attributes: [] }) //this should be unauthorized - case HttpStatusCode.Forbidden: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.NotFound: return opKnownFailure("officer-not-found", resp); - case HttpStatusCode.Conflict: return opKnownFailure("officer-disabled", resp); + case HttpStatusCode.Forbidden: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } @@ -116,11 +119,11 @@ export class TalerExchangeHttpClient { switch (resp.status) { case HttpStatusCode.NoContent: return opEmptySuccess() //FIXME: this should be unauthorized - case HttpStatusCode.Forbidden: return opKnownFailure("unauthorized", resp); - case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); + case HttpStatusCode.Forbidden: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Unauthorized: return opKnownHttpFailure(resp.status, resp); //FIXME: this two need to be splitted by error code - case HttpStatusCode.NotFound: return opKnownFailure("officer-or-account-not-found", resp); - case HttpStatusCode.Conflict: return opKnownFailure("officer-disabled-or-recent-decision", resp); + case HttpStatusCode.NotFound: return opKnownHttpFailure(resp.status, resp); + case HttpStatusCode.Conflict: return opKnownHttpFailure(resp.status, resp); default: return opUnknownFailure(resp, await resp.text()) } } diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts index a6dc4661f..f8d6a4cff 100644 --- a/packages/taler-util/src/http-client/merchant.ts +++ b/packages/taler-util/src/http-client/merchant.ts @@ -12,7 +12,7 @@ export type TalerMerchantErrorsByMethod<prop extends keyof TalerMerchantHttpClie */ export class TalerMerchantHttpClient { httpLib: HttpRequestLibrary; - public readonly PROTOCOL_VERSION = "5:0:1"; + public readonly PROTOCOL_VERSION = "6:0:2"; constructor( readonly baseUrl: string, diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index 75241aa30..2172eee39 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -54,15 +54,17 @@ export type PaginationParams = { */ limit?: number; /** - * milliseconds the server should wait for at least one result to be shown - */ - timoutMs?: number; - /** * order */ order: "asc" | "dec"; }; +export type LongPollParams = { + /** + * milliseconds the server should wait for at least one result to be shown + */ + timeoutMs?: number; +}; /// /// HASH /// @@ -273,13 +275,13 @@ export const codecForCoreBankConfig = (): Codec<TalerCorebankApi.Config> => .property("name", codecForConstString("libeufin-bank")) .property("version", codecForString()) .property("allow_conversion", codecForBoolean()) - .property("allow_deletions", codecForBoolean()) .property("allow_registrations", codecForBoolean()) - .property("allow_edit_cashout_payto_uri", codecForBoolean()) + .property("allow_deletions", codecForBoolean()) .property("allow_edit_name", codecForBoolean()) + .property("allow_edit_cashout_payto_uri", codecForBoolean()) .property("default_debit_threshold", codecForAmountString()) - .property("currency_specification", codecForCurrencySpecificiation()) .property("currency", codecForString()) + .property("currency_specification", codecForCurrencySpecificiation()) .property("supported_tan_channels", codecForList(codecForEither( codecForConstString(TalerCorebankApi.TanChannel.SMS), codecForConstString(TalerCorebankApi.TanChannel.EMAIL), @@ -334,10 +336,11 @@ export const codecForPublicAccountsResponse = export const codecForAccountMinimalData = (): Codec<TalerCorebankApi.AccountMinimalData> => buildCodecForObject<TalerCorebankApi.AccountMinimalData>() + .property("username", codecForString()) + .property("name", codecForString()) + .property("payto_uri", codecForPaytoString()) .property("balance", codecForBalance()) .property("debit_threshold", codecForAmountString()) - .property("name", codecForString()) - .property("username", codecForString()) .property("is_public", codecForBoolean()) .property("is_taler_exchange", codecForBoolean()) .build("TalerCorebankApi.AccountMinimalData"); @@ -377,13 +380,6 @@ export const codecForChallengeContactData = export const codecForWithdrawalPublicInfo = (): Codec<TalerCorebankApi.WithdrawalPublicInfo> => buildCodecForObject<TalerCorebankApi.WithdrawalPublicInfo>() - .property("username", codecForString()) - .property("amount", codecForAmountString()) - .property( - "selected_exchange_account", - codecOptional(codecForPaytoString()), - ) - .property("selected_reserve_pub", codecOptional(codecForString())) .property( "status", codecForEither( @@ -393,6 +389,13 @@ export const codecForWithdrawalPublicInfo = codecForConstString("confirmed"), ), ) + .property("amount", codecForAmountString()) + .property("username", codecForString()) + .property("selected_reserve_pub", codecOptional(codecForString())) + .property( + "selected_exchange_account", + codecOptional(codecForPaytoString()), + ) .build("TalerCorebankApi.WithdrawalPublicInfo"); export const codecForBankAccountTransactionsResponse = @@ -469,15 +472,6 @@ export const codecForCashouts = (): Codec<TalerCorebankApi.Cashouts> => export const codecForCashoutInfo = (): Codec<TalerCorebankApi.CashoutInfo> => buildCodecForObject<TalerCorebankApi.CashoutInfo>() .property("cashout_id", codecForNumber()) - .property( - "status", - codecOptional( - codecForEither( - codecForConstString("pending"), - codecForConstString("aborted"), - codecForConstString("confirmed"), - )), - ) .build("TalerCorebankApi.CashoutInfo"); export const codecForGlobalCashouts = @@ -491,41 +485,15 @@ export const codecForGlobalCashoutInfo = buildCodecForObject<TalerCorebankApi.GlobalCashoutInfo>() .property("cashout_id", codecForNumber()) .property("username", codecForString()) - .property( - "status", - codecOptional( - codecForEither( - codecForConstString("pending"), - codecForConstString("aborted"), - codecForConstString("confirmed"), - )), - ) .build("TalerCorebankApi.GlobalCashoutInfo"); export const codecForCashoutStatusResponse = (): Codec<TalerCorebankApi.CashoutStatusResponse> => buildCodecForObject<TalerCorebankApi.CashoutStatusResponse>() - .property("amount_credit", codecForAmountString()) .property("amount_debit", codecForAmountString()) - .property("creation_time", codecForTimestamp) - .property( - "tan_channel", - codecOptional(codecForEither( - codecForConstString(TalerCorebankApi.TanChannel.SMS), - codecForConstString(TalerCorebankApi.TanChannel.EMAIL), - )), - ) + .property("amount_credit", codecForAmountString()) .property("subject", codecForString()) - .property("confirmation_time", codecOptional(codecForTimestamp)) - .property( - "status", - codecOptional(codecForEither( - codecForConstString("pending"), - codecForConstString("aborted"), - codecForConstString("confirmed"), - )), - ) - .property("tan_info", codecOptional(codecForString())) + .property("creation_time", codecForTimestamp) .build("TalerCorebankApi.CashoutStatusResponse"); export const codecForConversionRatesResponse = @@ -607,7 +575,6 @@ export const codecForBankWithdrawalOperationPostResponse = .property( "status", codecForEither( - codecForConstString("pending"), codecForConstString("selected"), codecForConstString("aborted"), codecForConstString("confirmed"), @@ -872,7 +839,7 @@ export const codecForConversionBankConfig = .property("fiat_currency", codecForString()) .property("fiat_currency_specification", codecForCurrencySpecificiation()) - .property("conversion_rate", codecOptional(codecForConversionInfo())) + .property("conversion_rate", (codecForConversionInfo())) .build("ConversionBankConfig.IntegrationConfig"); // export const codecFor = @@ -1177,7 +1144,7 @@ export namespace TalerBankConversionApi { // Extra conversion rate information. // Only present if server opts in to report the static conversion rate. - conversion_rate?: ConversionInfo; + conversion_rate: ConversionInfo; } export interface CashinConversionResponse { @@ -1564,6 +1531,9 @@ export namespace TalerCorebankApi { // Legal name of the account owner. name: string; + // Internal payto URI of this bank account. + payto_uri: PaytoString; + // current balance of the account balance: Balance; @@ -1638,14 +1608,6 @@ export namespace TalerCorebankApi { // otherwise the request will fail. amount_credit: AmountString; - // Which channel the TAN should be sent to. If - // this field is missing, it defaults to SMS. - // The default choice prefers to change the communication - // channel respect to the one used to issue this request. - /** - * @deprecated since 4, use 2fa - */ - tan_channel?: TanChannel; } export interface CashoutResponse { @@ -1680,10 +1642,6 @@ export namespace TalerCorebankApi { export interface GlobalCashoutInfo { cashout_id: number; username: string; - /** - * @deprecated since 4, use new 2fa - */ - status?: "pending" | "aborted" | "confirmed"; } export interface CashoutStatusResponse { @@ -1698,38 +1656,8 @@ export namespace TalerCorebankApi { // Transaction subject. subject: string; - // Fiat bank account that will receive the cashed out amount. - // Specified as a payto URI. - // credit_payto_uri: PaytoString; - // Time when the cashout was created. creation_time: Timestamp; - - /** - * @deprecated since 4, use new 2fa - */ - status?: "pending" | "aborted" | "confirmed"; - - // Time when the cashout was confirmed via its TAN. - // Missing when the operation wasn't confirmed yet. - /** - * @deprecated since 4, use new 2fa - */ - confirmation_time?: Timestamp; - - // Channel of the last successful transmission of the TAN challenge. - // Missing when all transmissions failed. - /** - * @deprecated since 4, use new 2fa - */ - tan_channel?: TanChannel; - - // Info of the last successful transmission of the TAN challenge. - // Missing when all transmissions failed. - /** - * @deprecated since 4, use new 2fa - */ - tan_info?: string; } export interface ConversionRatesResponse { diff --git a/packages/taler-util/src/http-client/utils.ts b/packages/taler-util/src/http-client/utils.ts index ab6f809ef..e4b874c2f 100644 --- a/packages/taler-util/src/http-client/utils.ts +++ b/packages/taler-util/src/http-client/utils.ts @@ -1,6 +1,6 @@ import { base64FromArrayBuffer } from "../base64.js"; import { stringToBytes } from "../taler-crypto.js"; -import { AccessToken, PaginationParams } from "./types.js"; +import { AccessToken, LongPollParams, PaginationParams } from "./types.js"; /** * Helper function to generate the "Authorization" HTTP header. @@ -25,9 +25,6 @@ export function makeBearerTokenAuthHeader(token: AccessToken): string { */ export function addPaginationParams(url: URL, pagination?: PaginationParams) { if (!pagination) return; - if (pagination.timoutMs) { - url.searchParams.set("long_poll_ms", String(pagination.timoutMs)) - } if (pagination.offset) { url.searchParams.set("start", pagination.offset) } @@ -36,3 +33,10 @@ export function addPaginationParams(url: URL, pagination?: PaginationParams) { //always send delta url.searchParams.set("delta", String(order * limit)) } + +export function addLongPollingParam(url: URL, param?: LongPollParams) { + if (!param) return; + if (param.timeoutMs) { + url.searchParams.set("long_poll_ms", String(param.timeoutMs)) + } +} |