/*
This file is part of GNU Taler
(C) 2022 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 {
AmountJson,
Amounts,
Logger
} from "@gnu-taler/taler-util";
import {
createPlatformHttpLib,
expectSuccessResponseOrThrow,
HttpRequestLibrary,
readSuccessResponseJsonOrThrow
} from "@gnu-taler/taler-util/http";
import { AccessToken, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashoutConversionResponse, codecForCashoutPending, codecForCashouts, codecForCashoutStatusResponse, codecForConversionRatesResponse, codecForCoreBankConfig, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse, codecForTokenSuccessResponse, TalerAuthentication, TalerCorebankApi } from "./types.js";
import { addPaginationParams, makeBasicAuthHeader, makeBearerTokenAuthHeader, PaginationParams, UserAndPassword, UserAndToken } from "./utils.js";
import { TalerRevenueHttpClient } from "./bank-revenue.js";
import { TalerWireGatewayHttpClient } from "./bank-wire.js";
import { TalerBankIntegrationHttpClient } from "./bank-integration.js";
const logger = new Logger("http-client/core-bank.ts");
export class TalerCoreBankHttpClient {
httpLib: HttpRequestLibrary;
constructor(
private baseUrl: string,
httpClient?: HttpRequestLibrary,
) {
this.httpLib = httpClient ?? createPlatformHttpLib();
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token
*
* @returns
*/
async createAccessToken(
auth: UserAndPassword,
body: TalerAuthentication.TokenRequest,
): Promise {
const url = new URL(`accounts/${auth.username}/token`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
Authorization: makeBasicAuthHeader(auth.username, auth.password),
},
body
});
return readSuccessResponseJsonOrThrow(resp, codecForTokenSuccessResponse());
}
async deleteAccessToken(
auth: UserAndToken,
): Promise {
const url = new URL(`accounts/${auth.username}/token`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "DELETE",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token),
}
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME
*
*/
async getConfig(): Promise {
const url = new URL(`config`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET"
});
return readSuccessResponseJsonOrThrow(resp, codecForCoreBankConfig());
}
//
// ACCOUNTS
//
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts
*
*/
async createAccount(auth: AccessToken, body: TalerCorebankApi.RegisterAccountRequest): Promise {
const url = new URL(`accounts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
body,
headers: {
Authorization: makeBearerTokenAuthHeader(auth)
},
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#delete--accounts-$USERNAME
*
*/
async deleteAccount(auth: UserAndToken): Promise {
const url = new URL(`accounts/${auth.username}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "DELETE",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#patch--accounts-$USERNAME
*
*/
async updateAccount(auth: UserAndToken, body: TalerCorebankApi.AccountReconfiguration): Promise {
const url = new URL(`accounts/${auth.username}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "PATCH",
body,
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#patch--accounts-$USERNAME-auth
*
*/
async updatePassword(auth: UserAndToken, body: TalerCorebankApi.AccountPasswordChange): Promise {
const url = new URL(`accounts/${auth.username}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "PATCH",
body,
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/get-$BANK_API_BASE_URL-public-accounts
*
*/
async getPublicAccounts(): Promise {
const url = new URL(`public-accounts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
},
});
return readSuccessResponseJsonOrThrow(resp, codecForPublicAccountsResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#get--accounts
*
*/
async getAccounts(auth: AccessToken): Promise {
const url = new URL(`accounts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForListBankAccountsResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME
*
*/
async getAccount(auth: UserAndToken): Promise {
const url = new URL(`accounts/${auth.username}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForAccountData());
}
//
// TRANSACTIONS
//
/**
* https://docs.taler.net/core/api-corebank.html#get-$BANK_API_BASE_URL-accounts-$account_name-transactions
*
*/
async getTransactions(auth: UserAndToken, pagination?: PaginationParams): Promise {
const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl);
addPaginationParams(url, pagination)
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForBankAccountTransactionsResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#get-$BANK_API_BASE_URL-accounts-$account_name-transactions-$transaction_id
*
*/
async getTransactionById(auth: UserAndToken, txid: number): Promise {
const url = new URL(`accounts/${auth.username}/transactions/${String(txid)}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForBankAccountTransactionInfo());
}
/**
* https://docs.taler.net/core/api-corebank.html#post-$BANK_API_BASE_URL-accounts-$account_name-transactions
*
*/
async createTransaction(auth: UserAndToken, body: TalerCorebankApi.CreateBankAccountTransactionCreate): Promise {
const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
body,
});
return expectSuccessResponseOrThrow(resp);
}
//
// WITHDRAWALS
//
/**
* https://docs.taler.net/core/api-corebank.html#post-$BANK_API_BASE_URL-accounts-$account_name-withdrawals
*
*/
async createWithdrawal(auth: UserAndToken, body: TalerCorebankApi.BankAccountCreateWithdrawalRequest): Promise {
const url = new URL(`accounts/${auth.username}/withdrawals`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
body,
});
return readSuccessResponseJsonOrThrow(resp, codecForBankAccountCreateWithdrawalResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#post-$BANK_API_BASE_URL-accounts-$account_name-withdrawals
*
*/
async getWithdrawalById(wid: string): Promise {
const url = new URL(`withdrawals/${wid}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
});
return readSuccessResponseJsonOrThrow(resp, codecForBankAccountGetWithdrawalResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#post-$BANK_API_BASE_URL-withdrawals-$withdrawal_id-abort
*
*/
async abortWithdrawalById(wid: string): Promise {
const url = new URL(`withdrawals/${wid}/abort`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#post-$BANK_API_BASE_URL-withdrawals-$withdrawal_id-confirm
*
*/
async confirmWithdrawalById(wid: string): Promise {
const url = new URL(`withdrawals/${wid}/confirm`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
});
return expectSuccessResponseOrThrow(resp);
}
//
// CASHOUTS
//
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts
*
*/
async createCashout(auth: UserAndToken, body: TalerCorebankApi.CashoutRequest): Promise {
const url = new URL(`accounts/${auth.username}/cashouts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
body,
});
return readSuccessResponseJsonOrThrow(resp, codecForCashoutPending());
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-abort
*
*/
async abortCashoutById(auth: UserAndToken, cid: string): Promise {
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)
},
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-confirm
*
*/
async confirmCashoutById(auth: UserAndToken, cid: string, body: TalerCorebankApi.CashoutConfirmRequest): Promise {
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,
});
return expectSuccessResponseOrThrow(resp);
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-confirm
*
*/
async getCashoutRate(conversion: { debit?: AmountJson, credit?: AmountJson }): Promise {
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_debit", Amounts.stringify(conversion.credit))
}
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
});
return readSuccessResponseJsonOrThrow(resp, codecForCashoutConversionResponse());
}
/**
* https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts
*
*/
async getAccountCashouts(auth: UserAndToken): Promise {
const url = new URL(`accounts/${auth.username}/cashouts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForCashouts());
}
/**
* https://docs.taler.net/core/api-corebank.html#get--cashouts
*
*/
async getGlobalCashouts(auth: AccessToken): Promise {
const url = new URL(`cashouts`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForGlobalCashouts());
}
/**
* https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts-$CASHOUT_ID
*
*/
async getCashoutById(auth: UserAndToken, cid: string): Promise {
const url = new URL(`accounts/${auth.username}/cashouts/${cid}`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
headers: {
Authorization: makeBearerTokenAuthHeader(auth.token)
},
});
return readSuccessResponseJsonOrThrow(resp, codecForCashoutStatusResponse());
}
//
// CONVERSION RATE
//
/**
* https://docs.taler.net/core/api-corebank.html#get--conversion-rates
*
*/
async getConversionRates(): Promise {
const url = new URL(`conversion-rates`, this.baseUrl);
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
});
return readSuccessResponseJsonOrThrow(resp, codecForConversionRatesResponse());
}
//
// MONITOR
//
/**
* https://docs.taler.net/core/api-corebank.html#get--monitor
*
*/
async getMonitor(params: { timeframe: TalerCorebankApi.MonitorTimeframeParam, which: number }): Promise {
const url = new URL(`monitor`, this.baseUrl);
url.searchParams.set("timeframe", params.timeframe.toString())
url.searchParams.set("which", String(params.which))
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
});
return readSuccessResponseJsonOrThrow(resp, codecForMonitorResponse());
}
//
// Others API
//
/**
* https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api
*
*/
getIntegrationAPI(): TalerBankIntegrationHttpClient {
const url = new URL(`taler-integration`, this.baseUrl);
return new TalerBankIntegrationHttpClient(url.href, this.httpLib)
}
/**
* https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api
*
*/
getWireGatewayAPI(username: string): TalerWireGatewayHttpClient {
const url = new URL(`accounts/${username}/taler-wire-gateway`, this.baseUrl);
return new TalerWireGatewayHttpClient(url.href, username, this.httpLib)
}
/**
* https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api
*
*/
getRevenueAPI(username: string): TalerRevenueHttpClient {
const url = new URL(`accounts/${username}/taler-revenue`, this.baseUrl);
return new TalerRevenueHttpClient(url.href, username, this.httpLib,)
}
}