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 { TalerErrorCode } from "../taler-error-codes.js"; import { codecForTalerErrorDetail } from "../wallet-types.js"; import { AccessToken, TalerBankConversionApi, UserAndToken, codecForCashinConversionResponse, codecForCashoutConversionResponse, codecForConversionBankConfig } from "./types.js"; import { makeBearerTokenAuthHeader } from "./utils.js"; export type TalerBankConversionResultByMethod = ResultByMethod export type TalerBankConversionErrorsByMethod = FailCasesByMethod /** * The API is used by the wallets. */ export class TalerBankConversionHttpClient { httpLib: HttpRequestLibrary; constructor( readonly baseUrl: string, httpClient?: HttpRequestLibrary, ) { this.httpLib = httpClient ?? createPlatformHttpLib(); } /** * https://docs.taler.net/core/api-bank-conversion-info.html#get--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, codecForConversionBankConfig()) default: return opUnknownFailure(resp, await resp.text()) } } /** * https://docs.taler.net/core/api-bank-conversion-info.html#get--cashin-rate * */ async getCashinRate(conversion: { debit?: AmountJson, credit?: AmountJson }) { const url = new URL(`cashin-rate`, this.baseUrl); if (conversion.debit) { url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit)) } if (conversion.credit) { url.searchParams.set("amount_credit", Amounts.stringify(conversion.credit)) } const resp = await this.httpLib.fetch(url.href, { method: "GET", }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForCashinConversionResponse()) case HttpStatusCode.BadRequest: { 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); default: return opUnknownFailure(resp, body) } } case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp); case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); default: return opUnknownFailure(resp, await resp.text()) } } /** * https://docs.taler.net/core/api-bank-conversion-info.html#get--cashout-rate * */ async getCashoutRate(conversion: { debit?: AmountJson, credit?: AmountJson }) { const url = new URL(`cashout-rate`, this.baseUrl); if (conversion.debit) { url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit)) } if (conversion.credit) { url.searchParams.set("amount_credit", Amounts.stringify(conversion.credit)) } const resp = await this.httpLib.fetch(url.href, { method: "GET", }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutConversionResponse()) case HttpStatusCode.BadRequest: { 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); default: return opUnknownFailure(resp, body) } } case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp); case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); default: return opUnknownFailure(resp, await resp.text()) } } /** * https://docs.taler.net/core/api-bank-conversion-info.html#post--conversion-rate * */ async updateConversionRate(auth: AccessToken, body: TalerBankConversionApi.ConversionRate) { const url = new URL(`conversion-rate`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { Authorization: makeBearerTokenAuthHeader(auth) }, body }); switch (resp.status) { case HttpStatusCode.NoContent: return opEmptySuccess() case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp); case HttpStatusCode.NotImplemented: return opKnownFailure("conversion-not-supported", resp); default: return opUnknownFailure(resp, await resp.text()) } } }