/* This file is part of GNU Taler (C) 2022-2024 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ import { HttpRequestLibrary, makeBasicAuthHeader, readTalerErrorResponse, } from "../http-common.js"; import { HttpStatusCode } from "../http-status-codes.js"; import { createPlatformHttpLib } from "../http.js"; import { FailCasesByMethod, ResultByMethod, opFixedSuccess, opKnownHttpFailure, opSuccessFromHttp, opUnknownFailure, } from "../operation.js"; import { codecForAddIncomingResponse, codecForIncomingHistory, codecForOutgoingHistory, codecForTransferResponse, } from "../types-taler-wire-gateway.js"; import { addLongPollingParam, addPaginationParams } from "./utils.js"; import { LongPollParams, PaginationParams } from "../types-taler-common.js"; import * as TalerWireGatewayApi from "../types-taler-wire-gateway.js"; export type TalerWireGatewayResultByMethod< prop extends keyof TalerWireGatewayHttpClient, > = ResultByMethod; export type TalerWireGatewayErrorsByMethod< prop extends keyof TalerWireGatewayHttpClient, > = FailCasesByMethod; /** * The API is used by the exchange to trigger transactions and query * incoming transactions, as well as by the auditor to query incoming * and outgoing transactions. * * https://docs.taler.net/core/api-bank-wire.html */ export class TalerWireGatewayHttpClient { httpLib: HttpRequestLibrary; constructor( readonly baseUrl: string, readonly username: string, httpClient?: HttpRequestLibrary, ) { 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 readTalerErrorResponse(resp)) // } // } /** * https://docs.taler.net/core/api-bank-wire.html#post--transfer * */ async transfer(auth: string, body: TalerWireGatewayApi.TransferRequest) { const url = new URL(`transfer`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { Authorization: makeBasicAuthHeader(this.username, auth), }, body, }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForTransferResponse()); //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 readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-bank-wire.html#get--history-incoming * */ async getHistoryIncoming( auth: string, params?: PaginationParams & LongPollParams, ) { const url = new URL(`history/incoming`, this.baseUrl); addPaginationParams(url, params); addLongPollingParam(url, params); const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { Authorization: makeBasicAuthHeader(this.username, auth), }, }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForIncomingHistory()); //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 readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-bank-wire.html#get--history-outgoing * */ async getHistoryOutgoing( auth: string, params?: PaginationParams & LongPollParams, ) { const url = new URL(`history/outgoing`, this.baseUrl); addPaginationParams(url, params); addLongPollingParam(url, params); const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { Authorization: makeBasicAuthHeader(this.username, auth), }, }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForOutgoingHistory()); //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 readTalerErrorResponse(resp)); } } /** * https://docs.taler.net/core/api-bank-wire.html#post--admin-add-incoming * */ async addIncoming( auth: string, body: TalerWireGatewayApi.AddIncomingRequest, ) { const url = new URL(`admin/add-incoming`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "POST", headers: { Authorization: makeBasicAuthHeader(this.username, auth), }, body, }); switch (resp.status) { case HttpStatusCode.Ok: return opSuccessFromHttp(resp, codecForAddIncomingResponse()); //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 readTalerErrorResponse(resp)); } } }