summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-03-08 12:19:20 -0300
committerSebastian <sebasjm@gmail.com>2024-03-08 12:19:20 -0300
commite0e82cdf07930d766081e42203c5a4e66d43191f (patch)
tree0c0b96cb88d701c7b19b0ef34ec1c67255a2f49e
parentb3ae213bc5987fbb6a2ce5c08d626f9f65508b03 (diff)
downloadwallet-core-e0e82cdf07930d766081e42203c5a4e66d43191f.tar.gz
wallet-core-e0e82cdf07930d766081e42203c5a4e66d43191f.tar.bz2
wallet-core-e0e82cdf07930d766081e42203c5a4e66d43191f.zip
wip #8489
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/testing.tsx8
-rw-r--r--packages/demobank-ui/src/Routing.tsx9
-rw-r--r--packages/demobank-ui/src/context/config.ts201
-rw-r--r--packages/demobank-ui/src/hooks/account.ts12
-rw-r--r--packages/demobank-ui/src/hooks/regional.ts28
-rw-r--r--packages/demobank-ui/src/pages/LoginForm.tsx5
-rw-r--r--packages/demobank-ui/src/pages/OperationState/state.ts10
-rw-r--r--packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx2
-rw-r--r--packages/demobank-ui/src/pages/QrCodeSection.tsx2
-rw-r--r--packages/demobank-ui/src/pages/RegistrationPage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/SolveChallengePage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx2
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx2
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx4
-rw-r--r--packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx2
-rw-r--r--packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx2
-rw-r--r--packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx2
-rw-r--r--packages/demobank-ui/src/pages/admin/DownloadStats.tsx2
-rw-r--r--packages/demobank-ui/src/pages/admin/RemoveAccount.tsx2
-rw-r--r--packages/demobank-ui/src/pages/regional/ConversionConfig.tsx6
-rw-r--r--packages/demobank-ui/src/pages/regional/CreateCashout.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/testing.tsx8
-rw-r--r--packages/taler-util/src/http-client/bank-conversion.ts13
-rw-r--r--packages/taler-util/src/http-client/bank-core.ts78
-rw-r--r--packages/taler-util/src/http-client/utils.ts8
-rw-r--r--packages/taler-util/src/index.ts1
26 files changed, 213 insertions, 202 deletions
diff --git a/packages/auditor-backoffice-ui/src/hooks/testing.tsx b/packages/auditor-backoffice-ui/src/hooks/testing.tsx
index 3ea22475b..20b9c8a35 100644
--- a/packages/auditor-backoffice-ui/src/hooks/testing.tsx
+++ b/packages/auditor-backoffice-ui/src/hooks/testing.tsx
@@ -27,7 +27,7 @@ import { ApiContextProvider } from "@gnu-taler/web-util/browser";
import { BackendContextProvider } from "../context/backend.js";
import { InstanceContextProvider } from "../context/instance.js";
import { HttpResponseOk, RequestOptions } from "@gnu-taler/web-util/browser";
-import { TalerBankIntegrationHttpClient, TalerCoreBankHttpClient } from "@gnu-taler/taler-util";
+import { TalerBankIntegrationHttpClient, TalerCoreBankHttpClient, TalerRevenueHttpClient, TalerWireGatewayHttpClient } from "@gnu-taler/taler-util";
export class ApiMockEnvironment extends MockEnvironment {
constructor(debug = false) {
@@ -144,9 +144,9 @@ export class ApiMockEnvironment extends MockEnvironment {
}
const bankCore = new TalerCoreBankHttpClient("http://localhost", mockHttpClient)
- const bankIntegration = bankCore.getIntegrationAPI()
- const bankRevenue = bankCore.getRevenueAPI("a")
- const bankWire = bankCore.getWireGatewayAPI("b")
+ const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI(), mockHttpClient)
+ const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a"), "a", mockHttpClient)
+ const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b"), "b", mockHttpClient)
return (
<BackendContextProvider defaultUrl="http://backend">
diff --git a/packages/demobank-ui/src/Routing.tsx b/packages/demobank-ui/src/Routing.tsx
index c85d74e17..f9b388ed1 100644
--- a/packages/demobank-ui/src/Routing.tsx
+++ b/packages/demobank-ui/src/Routing.tsx
@@ -94,7 +94,7 @@ function PublicRounting({
const { i18n } = useTranslationContext();
const location = useCurrentLocation(publicPages);
const { navigateTo } = useNavigationContext();
- const { api } = useBankCoreApiContext();
+ const { bank, authenticator } = useBankCoreApiContext();
const [notification, notify, handleError] = useLocalNotification();
useEffect(() => {
@@ -109,8 +109,7 @@ function PublicRounting({
async function doAutomaticLogin(username: string, password: string) {
await handleError(async () => {
- const resp = await api
- .getAuthenticationAPI(username)
+ const resp = await authenticator(username)
.createAccessToken(password, {
scope: "readwrite",
duration: { d_us: "forever" },
@@ -570,11 +569,11 @@ function PrivateRouting({
routeMyAccountDetails={privatePages.myAccountDetails}
routeMyAccountPassword={privatePages.myAccountPassword}
routeConversionConfig={privatePages.conversionConfig}
- routeCancel={privatePages.home}
+ routeCancel={privatePages.home}
onUpdateSuccess={() => {
navigateTo(privatePages.home.url({}))
}}
- />;
+ />;
}
case "homeWireTransfer": {
return (
diff --git a/packages/demobank-ui/src/context/config.ts b/packages/demobank-ui/src/context/config.ts
index 72c176679..39d12be86 100644
--- a/packages/demobank-ui/src/context/config.ts
+++ b/packages/demobank-ui/src/context/config.ts
@@ -15,20 +15,16 @@
*/
import {
- AccessToken,
- AmountJson,
- HttpStatusCode,
+ assertUnreachable,
LibtoolVersion,
- OperationFail,
- OperationOk,
- TalerBankConversionApi,
+ TalerBankConversionCacheEviction,
TalerBankConversionHttpClient,
TalerCorebankApi,
+ TalerAuthenticationHttpClient,
+ TalerCoreBankCacheEviction,
TalerCoreBankHttpClient,
- TalerError,
- UserAndToken,
+ TalerError
} from "@gnu-taler/taler-util";
-import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
import {
BrowserHttpLib,
ErrorLoading,
@@ -61,7 +57,9 @@ import {
export type Type = {
url: URL;
config: TalerCorebankApi.Config;
- api: TalerCoreBankHttpClient;
+ bank: TalerCoreBankHttpClient;
+ conversion: TalerBankConversionHttpClient;
+ authenticator: (user: string) => TalerAuthenticationHttpClient;
hints: VersionHint[];
};
@@ -95,13 +93,14 @@ export const BankCoreApiProvider = ({
}): VNode => {
const [checked, setChecked] = useState<ConfigResult>();
const { i18n } = useTranslationContext();
- const url = new URL(baseUrl);
- const api = new CacheAwareTalerCoreBankHttpClient(url.href, new BrowserHttpLib());
+
+ const { bankClient, conversionClient, authClient } = buildApiClient(new URL(baseUrl))
+
useEffect(() => {
- api
+ bankClient
.getConfig()
.then((resp) => {
- if (api.isCompatible(resp.body.version)) {
+ if (bankClient.isCompatible(resp.body.version)) {
setChecked({ type: "ok", config: resp.body, hints: [] });
} else {
// this API supports version 3.0.3
@@ -116,7 +115,7 @@ export const BankCoreApiProvider = ({
setChecked({
type: "incompatible",
result: resp.body,
- supported: api.PROTOCOL_VERSION,
+ supported: bankClient.PROTOCOL_VERSION,
});
}
}
@@ -146,9 +145,11 @@ export const BankCoreApiProvider = ({
});
}
const value: Type = {
- url,
+ url: new URL(bankClient.baseUrl),
config: checked.config,
- api: api,
+ bank: bankClient,
+ conversion: conversionClient,
+ authenticator: authClient,
hints: checked.hints,
};
return h(Context.Provider, {
@@ -158,100 +159,84 @@ export const BankCoreApiProvider = ({
};
/**
- *
+ * build http client with cache breaker due to SWR
+ * @param url
+ * @returns
*/
-class CacheAwareTalerBankConversionHttpClient extends TalerBankConversionHttpClient {
- constructor(baseUrl: string, httpClient?: HttpRequestLibrary) {
- super(baseUrl, httpClient);
- }
- async updateConversionRate(auth: AccessToken, body: TalerBankConversionApi.ConversionRate) {
- const resp = await super.updateConversionRate(auth, body);
- if (resp.type === "ok") {
- await revalidateConversionInfo();
- }
- return resp
- }
-}
+function buildApiClient(url: URL) {
+ const httpLib = new BrowserHttpLib();
-class CacheAwareTalerCoreBankHttpClient extends TalerCoreBankHttpClient {
- constructor(baseUrl: string, httpClient?: HttpRequestLibrary) {
- super(baseUrl, httpClient);
- }
- async deleteAccount(auth: UserAndToken, cid?: string | undefined) {
- const resp = await super.deleteAccount(auth, cid);
- if (resp.type === "ok") {
- await revalidatePublicAccounts();
- await revalidateBusinessAccounts();
- }
- return resp;
- }
- async createAccount(
- auth: AccessToken,
- body: TalerCorebankApi.RegisterAccountRequest,
- ) {
- const resp = await super.createAccount(auth, body);
- if (resp.type === "ok") {
- // admin balance change on new account
- await revalidateAccountDetails();
- await revalidateTransactions();
- await revalidatePublicAccounts();
- await revalidateBusinessAccounts();
- }
- return resp;
- }
- async updateAccount(
- auth: UserAndToken,
- body: TalerCorebankApi.AccountReconfiguration,
- cid?: string | undefined,
- ) {
- const resp = await super.updateAccount(auth, body, cid);
- if (resp.type === "ok") {
- await revalidateAccountDetails();
- }
- return resp;
- }
- async createTransaction(
- auth: UserAndToken,
- body: TalerCorebankApi.CreateTransactionRequest,
- cid?: string | undefined,
- ) {
- const resp = await super.createTransaction(auth, body, cid);
- if (resp.type === "ok") {
- await revalidateAccountDetails();
- await revalidateTransactions();
- }
- return resp;
- }
- async confirmWithdrawalById(
- auth: UserAndToken,
- wid: string,
- cid?: string | undefined,
- ) {
- const resp = await super.confirmWithdrawalById(auth, wid, cid);
- if (resp.type === "ok") {
- await revalidateAccountDetails();
- await revalidateTransactions();
+ const bankClient = new TalerCoreBankHttpClient(url.href, httpLib, {
+ async notifySuccess(op) {
+ switch (op) {
+ case TalerCoreBankCacheEviction.DELELE_ACCOUNT: {
+ await Promise.all([
+ revalidatePublicAccounts(),
+ revalidateBusinessAccounts(),
+ ]);
+ return
+ }
+ case TalerCoreBankCacheEviction.CREATE_ACCOUNT: {
+ // admin balance change on new account
+ await Promise.all([
+ revalidateAccountDetails(),
+ revalidateTransactions(),
+ revalidatePublicAccounts(),
+ revalidateBusinessAccounts(),
+ ])
+ return;
+ }
+ case TalerCoreBankCacheEviction.UPDATE_ACCOUNT: {
+ await Promise.all([
+ revalidateAccountDetails(),
+ ])
+ return;
+ }
+ case TalerCoreBankCacheEviction.CREATE_TRANSACTION: {
+ await Promise.all([
+ revalidateAccountDetails(),
+ revalidateTransactions(),
+ ])
+ return;
+ }
+ case TalerCoreBankCacheEviction.CONFIRM_WITHDRAWAL: {
+ await Promise.all([
+ revalidateAccountDetails(),
+ revalidateTransactions(),
+ ])
+ return;
+ }
+ case TalerCoreBankCacheEviction.CREATE_CASHOUT: {
+ await Promise.all([
+ revalidateAccountDetails(),
+ revalidateCashouts(),
+ revalidateTransactions(),
+ ])
+ return;
+ }
+ case TalerCoreBankCacheEviction.UPDATE_PASSWORD:
+ case TalerCoreBankCacheEviction.ABORT_WITHDRAWAL:
+ case TalerCoreBankCacheEviction.CREATE_WITHDRAWAL:
+ return;
+ default:
+ assertUnreachable(op)
+ }
}
- return resp;
- }
- async createCashout(
- auth: UserAndToken,
- body: TalerCorebankApi.CashoutRequest,
- cid?: string | undefined,
- ) {
- const resp = await super.createCashout(auth, body, cid);
- if (resp.type === "ok") {
- await revalidateAccountDetails();
- await revalidateCashouts();
- await revalidateTransactions();
+ });
+ const conversionClient = new TalerBankConversionHttpClient(bankClient.getConversionInfoAPI(), httpLib, {
+ async notifySuccess(op) {
+ switch (op) {
+ case TalerBankConversionCacheEviction.UPDATE_RATE: {
+ await revalidateConversionInfo();
+ return
+ }
+ default:
+ assertUnreachable(op)
+ }
}
- return resp;
- }
-
- getConversionInfoAPI(): TalerBankConversionHttpClient {
- const api = super.getConversionInfoAPI();
- return new CacheAwareTalerBankConversionHttpClient(api.baseUrl, this.httpLib)
- }
+ });
+ const authClient = (user: string) => new TalerAuthenticationHttpClient(bankClient.getAuthenticationAPI(user), user, httpLib);
+ return { bankClient, conversionClient, authClient }
}
export const BankCoreApiProviderTesting = ({
@@ -267,7 +252,7 @@ export const BankCoreApiProviderTesting = ({
url: new URL(url),
config: state,
// @ts-expect-error this API is not being used, not really needed
- api: undefined,
+ bank: undefined,
hints: [],
};
diff --git a/packages/demobank-ui/src/hooks/account.ts b/packages/demobank-ui/src/hooks/account.ts
index 61a11b1a5..aa0745253 100644
--- a/packages/demobank-ui/src/hooks/account.ts
+++ b/packages/demobank-ui/src/hooks/account.ts
@@ -44,7 +44,7 @@ export function revalidateAccountDetails() {
export function useAccountDetails(account: string) {
const { state: credentials } = useSessionState();
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
async function fetcher([username, token]: [string, AccessToken]) {
return await api.getAccount({ username, token });
@@ -66,7 +66,7 @@ export function revalidateWithdrawalDetails() {
}
export function useWithdrawalDetails(wid: string) {
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [latestStatus, setLatestStatus] = useState<WithdrawalOperationStatus>();
async function fetcher([wid, old_state]: [
@@ -117,7 +117,7 @@ export function useTransactionDetails(account: string, tid: number) {
const { state: credentials } = useSessionState();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
async function fetcher([username, token, txid]: [
string,
@@ -147,7 +147,7 @@ export function useTransactionDetails(account: string, tid: number) {
return undefined;
}
-export function revalidatePublicAccounts() {
+export async function revalidatePublicAccounts() {
return mutate(
(key) => Array.isArray(key) && key[key.length - 1] === "getPublicAccounts", undefined, { revalidate: true }
);
@@ -158,7 +158,7 @@ export function usePublicAccounts(
) {
const [offset, setOffset] = useState<number | undefined>(initial);
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
async function fetcher([account, txid]: [
string | undefined,
@@ -233,7 +233,7 @@ export function useTransactions(account: string, initial?: number) {
credentials.status !== "loggedIn" ? undefined : credentials.token;
const [offset, setOffset] = useState<number | undefined>(initial);
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
async function fetcher([username, token, txid]: [
string,
diff --git a/packages/demobank-ui/src/hooks/regional.ts b/packages/demobank-ui/src/hooks/regional.ts
index 3469bf501..bf948d293 100644
--- a/packages/demobank-ui/src/hooks/regional.ts
+++ b/packages/demobank-ui/src/hooks/regional.ts
@@ -60,10 +60,10 @@ export function revalidateConversionInfo() {
);
}
export function useConversionInfo() {
- const { api, config } = useBankCoreApiContext();
+ const { conversion, config } = useBankCoreApiContext();
async function fetcher() {
- return await api.getConversionInfoAPI().getConfig();
+ return await conversion.getConfig();
}
const { data, error } = useSWR<
TalerBankConversionResultByMethod<"getConfig">,
@@ -86,10 +86,10 @@ export function useConversionInfo() {
}
export function useCashinEstimator(): ConversionEstimators {
- const { api } = useBankCoreApiContext();
+ const { conversion } = useBankCoreApiContext();
return {
estimateByCredit: async (fiatAmount, fee) => {
- const resp = await api.getConversionInfoAPI().getCashinRate({
+ const resp = await conversion.getCashinRate({
credit: fiatAmount,
});
if (resp.type === "fail") {
@@ -114,7 +114,7 @@ export function useCashinEstimator(): ConversionEstimators {
};
},
estimateByDebit: async (regionalAmount, fee) => {
- const resp = await api.getConversionInfoAPI().getCashinRate({
+ const resp = await conversion.getCashinRate({
debit: regionalAmount,
});
if (resp.type === "fail") {
@@ -142,10 +142,10 @@ export function useCashinEstimator(): ConversionEstimators {
}
export function useCashoutEstimator(): ConversionEstimators {
- const { api } = useBankCoreApiContext();
+ const { bank, conversion } = useBankCoreApiContext();
return {
estimateByCredit: async (fiatAmount, fee) => {
- const resp = await api.getConversionInfoAPI().getCashoutRate({
+ const resp = await conversion.getCashoutRate({
credit: fiatAmount,
});
if (resp.type === "fail") {
@@ -170,7 +170,7 @@ export function useCashoutEstimator(): ConversionEstimators {
};
},
estimateByDebit: async (regionalAmount, fee) => {
- const resp = await api.getConversionInfoAPI().getCashoutRate({
+ const resp = await conversion.getCashoutRate({
debit: regionalAmount,
});
if (resp.type === "fail") {
@@ -204,14 +204,14 @@ export function useEstimator(): ConversionEstimators {
return useCashoutEstimator()
}
-export function revalidateBusinessAccounts() {
+export async function revalidateBusinessAccounts() {
return mutate((key) => Array.isArray(key) && key[key.length - 1] === "getAccounts", undefined, { revalidate: true });
}
export function useBusinessAccounts() {
const { state: credentials } = useSessionState();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [offset, setOffset] = useState<number | undefined>();
@@ -281,7 +281,7 @@ export function revalidateOnePendingCashouts() {
}
export function useOnePendingCashouts(account: string) {
const { state: credentials } = useSessionState();
- const { api, config } = useBankCoreApiContext();
+ const { bank: api, config } = useBankCoreApiContext();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
@@ -338,7 +338,7 @@ export function revalidateCashouts() {
}
export function useCashouts(account: string) {
const { state: credentials } = useSessionState();
- const { api, config } = useBankCoreApiContext();
+ const { bank: api, config } = useBankCoreApiContext();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
@@ -392,7 +392,7 @@ export function revalidateCashoutDetails() {
export function useCashoutDetails(cashoutId: number | undefined) {
const { state: credentials } = useSessionState();
const creds = credentials.status !== "loggedIn" ? undefined : credentials;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
async function fetcher([username, token, id]: [string, AccessToken, number]) {
return api.getCashoutById({ username, token }, id);
@@ -443,7 +443,7 @@ export function useLastMonitorInfo(
previousMoment: number,
timeframe: TalerCorebankApi.MonitorTimeframeParam,
) {
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const { state: credentials } = useSessionState();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx b/packages/demobank-ui/src/pages/LoginForm.tsx
index e62759415..bd20e79c8 100644
--- a/packages/demobank-ui/src/pages/LoginForm.tsx
+++ b/packages/demobank-ui/src/pages/LoginForm.tsx
@@ -53,7 +53,7 @@ export function LoginForm({
);
const [password, setPassword] = useState<string | undefined>();
const { i18n } = useTranslationContext();
- const { api } = useBankCoreApiContext();
+ const { authenticator } = useBankCoreApiContext();
const [notification, withErrorHandler] = useLocalNotificationHandler();
const { config } = useBankCoreApiContext();
@@ -77,8 +77,7 @@ export function LoginForm({
}
const loginHandler = !username || !password ? undefined : withErrorHandler(
- async () => api
- .getAuthenticationAPI(username)
+ async () => authenticator(username)
.createAccessToken(password, {
// scope: "readwrite" as "write", // FIX: different than merchant
scope: "readwrite",
diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts b/packages/demobank-ui/src/pages/OperationState/state.ts
index 693179d40..5baf2d51c 100644
--- a/packages/demobank-ui/src/pages/OperationState/state.ts
+++ b/packages/demobank-ui/src/pages/OperationState/state.ts
@@ -45,7 +45,7 @@ export function useComponentState({
const [bankState, updateBankState] = useBankState();
const { state: credentials } = useSessionState();
const creds = credentials.status !== "loggedIn" ? undefined : credentials;
- const { api } = useBankCoreApiContext();
+ const { bank } = useBankCoreApiContext();
const [failure, setFailure] = useState<
TalerCoreBankErrorsByMethod<"createWithdrawal"> | undefined
@@ -56,7 +56,7 @@ export function useComponentState({
// FIXME: if amount is not enough use balance
const parsedAmount = Amounts.parseOrThrow(`${currency}:${amount}`);
if (!creds) return;
- const resp = await api.createWithdrawal(creds, {
+ const resp = await bank.createWithdrawal(creds, {
amount: Amounts.stringify(parsedAmount),
});
if (resp.type === "fail") {
@@ -91,7 +91,7 @@ export function useComponentState({
async function doAbort() {
if (!creds) return;
- const resp = await api.abortWithdrawalById(creds, wid);
+ const resp = await bank.abortWithdrawalById(creds, wid);
if (resp.type === "ok") {
// updateBankState("currentWithdrawalOperationId", undefined)
onAbort();
@@ -104,7 +104,7 @@ export function useComponentState({
TalerCoreBankErrorsByMethod<"confirmWithdrawalById"> | undefined
> {
if (!creds) return;
- const resp = await api.confirmWithdrawalById(creds, wid);
+ const resp = await bank.confirmWithdrawalById(creds, wid);
if (resp.type === "ok") {
mutate(() => true); //clean withdrawal state
} else {
@@ -113,7 +113,7 @@ export function useComponentState({
}
const uri = stringifyWithdrawUri({
- bankIntegrationApiBaseUrl: api.getIntegrationAPI().baseUrl,
+ bankIntegrationApiBaseUrl: bank.getIntegrationAPI(),
withdrawalOperationId,
});
const parsedUri = parseWithdrawUri(uri);
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index f746094ce..791a3b440 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -81,7 +81,7 @@ export function PaytoWireTransferForm({
}: Props): VNode {
const [isRawPayto, setIsRawPayto] = useState(false);
const { state: credentials } = useSessionState();
- const { api, config, url } = useBankCoreApiContext();
+ const { bank: api, config, url } = useBankCoreApiContext();
const sendingToFixedAccount = withAccount !== undefined;
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index d4f5a5455..da11e631d 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -51,7 +51,7 @@ export function QrCodeSection({
const [notification, handleError] = useLocalNotificationHandler();
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const onAbortHandler = handleError(
async () => {
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index 18b4c470b..e9f7e602f 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -80,7 +80,7 @@ function RegistrationForm({
const [notification, _, handleError] = useLocalNotification();
const settings = useSettingsContext();
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
// const { register } = useTestingAPI();
const { i18n } = useTranslationContext();
diff --git a/packages/demobank-ui/src/pages/SolveChallengePage.tsx b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
index 7e117f535..b2e053b3c 100644
--- a/packages/demobank-ui/src/pages/SolveChallengePage.tsx
+++ b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
@@ -57,7 +57,7 @@ export function SolveChallengePage({
onChallengeCompleted: () => void;
routeClose: RouteDefinition;
}): VNode {
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const { i18n } = useTranslationContext();
const [bankState, updateBankState] = useBankState();
const [code, setCode] = useState<string | undefined>(undefined);
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index caf205f31..001d90fa1 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -63,7 +63,7 @@ function OldWithdrawalForm({
// const { navigateTo } = useNavigationContext();
const [bankState, updateBankState] = useBankState();
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const { state: credentials } = useSessionState();
const creds = credentials.status !== "loggedIn" ? undefined : credentials;
diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
index 4efc82017..5925719c3 100644
--- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
@@ -74,7 +74,7 @@ export function WithdrawalConfirmationQuestion({
const [notification, notify, handleError] = useLocalNotification();
- const { config, api } = useBankCoreApiContext();
+ const { config, bank: api } = useBankCoreApiContext();
async function doTransfer() {
await handleError(async () => {
diff --git a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
index 7075c34c6..973a23011 100644
--- a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
@@ -36,9 +36,9 @@ export function WithdrawalOperationPage({
routeClose: RouteDefinition;
routeWithdrawalDetails: RouteDefinition<{ wopid: string }>;
}): VNode {
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const uri = stringifyWithdrawUri({
- bankIntegrationApiBaseUrl: api.getIntegrationAPI().baseUrl,
+ bankIntegrationApiBaseUrl: api.getIntegrationAPI(),
withdrawalOperationId: operationId,
});
const parsedUri = parseWithdrawUri(uri);
diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
index 8ab3998ad..62c8df7f8 100644
--- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
@@ -67,7 +67,7 @@ export function ShowAccountDetails({
const { i18n } = useTranslationContext();
const { state: credentials } = useSessionState();
const creds = credentials.status !== "loggedIn" ? undefined : credentials;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const accountIsTheCurrentUser =
credentials.status === "loggedIn"
? credentials.username === account
diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
index b9a334088..e21ac2464 100644
--- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
@@ -65,7 +65,7 @@ export function UpdateAccountPassword({
const { state: credentials } = useSessionState();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [current, setCurrent] = useState<string | undefined>();
const [password, setPassword] = useState<string | undefined>();
diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
index 3ae2b636c..38119735e 100644
--- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
@@ -45,7 +45,7 @@ export function CreateNewAccount({
const { state: credentials } = useSessionState();
const token =
credentials.status !== "loggedIn" ? undefined : credentials.token;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [submitAccount, setSubmitAccount] = useState<
TalerCorebankApi.RegisterAccountRequest | undefined
diff --git a/packages/demobank-ui/src/pages/admin/DownloadStats.tsx b/packages/demobank-ui/src/pages/admin/DownloadStats.tsx
index 66ef73d19..fba366676 100644
--- a/packages/demobank-ui/src/pages/admin/DownloadStats.tsx
+++ b/packages/demobank-ui/src/pages/admin/DownloadStats.tsx
@@ -59,7 +59,7 @@ export function DownloadStats({ routeCancel }: Props): VNode {
credentials.status !== "loggedIn" || !credentials.isUserAdministrator
? undefined
: credentials;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [options, setOptions] = useState<Options>({
compareWithPrevious: true,
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index 6039db326..61def9a95 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -64,7 +64,7 @@ export function RemoveAccount({
const { state } = useSessionState();
const token = state.status !== "loggedIn" ? undefined : state.token;
- const { api } = useBankCoreApiContext();
+ const { bank: api } = useBankCoreApiContext();
const [notification, notify, handleError] = useLocalNotification();
const [, updateBankState] = useBankState();
diff --git a/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx b/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
index 63423353b..8845ec9a0 100644
--- a/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
+++ b/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
@@ -88,7 +88,7 @@ function useComponentState({
return () => {
const { i18n } = useTranslationContext();
- const { api, config } = useBankCoreApiContext();
+ const { bank, conversion, config } = useBankCoreApiContext();
const [notification, notify, handleError] = useLocalNotification();
@@ -153,9 +153,7 @@ function useComponentState({
if (!creds) return
await handleError(async () => {
if (status.status === "fail") return;
- const resp = await api
- .getConversionInfoAPI()
- .updateConversionRate(creds.token, status.result.conv)
+ const resp = await conversion.updateConversionRate(creds.token, status.result.conv)
if (resp.type === "ok") {
setSection("detail")
} else {
diff --git a/packages/demobank-ui/src/pages/regional/CreateCashout.tsx b/packages/demobank-ui/src/pages/regional/CreateCashout.tsx
index a5b8f774a..2f15d16b4 100644
--- a/packages/demobank-ui/src/pages/regional/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/regional/CreateCashout.tsx
@@ -86,7 +86,7 @@ export function CreateCashout({
const creds = credentials.status !== "loggedIn" ? undefined : credentials;
const [, updateBankState] = useBankState();
- const { api, config, hints } = useBankCoreApiContext();
+ const { bank: api, config, hints } = useBankCoreApiContext();
const [form, setForm] = useState<Partial<FormType>>({ isDebit: true });
const [notification, notify, handleError] = useLocalNotification();
const info = useConversionInfo();
diff --git a/packages/merchant-backoffice-ui/src/hooks/testing.tsx b/packages/merchant-backoffice-ui/src/hooks/testing.tsx
index 3ea22475b..20b9c8a35 100644
--- a/packages/merchant-backoffice-ui/src/hooks/testing.tsx
+++ b/packages/merchant-backoffice-ui/src/hooks/testing.tsx
@@ -27,7 +27,7 @@ import { ApiContextProvider } from "@gnu-taler/web-util/browser";
import { BackendContextProvider } from "../context/backend.js";
import { InstanceContextProvider } from "../context/instance.js";
import { HttpResponseOk, RequestOptions } from "@gnu-taler/web-util/browser";
-import { TalerBankIntegrationHttpClient, TalerCoreBankHttpClient } from "@gnu-taler/taler-util";
+import { TalerBankIntegrationHttpClient, TalerCoreBankHttpClient, TalerRevenueHttpClient, TalerWireGatewayHttpClient } from "@gnu-taler/taler-util";
export class ApiMockEnvironment extends MockEnvironment {
constructor(debug = false) {
@@ -144,9 +144,9 @@ export class ApiMockEnvironment extends MockEnvironment {
}
const bankCore = new TalerCoreBankHttpClient("http://localhost", mockHttpClient)
- const bankIntegration = bankCore.getIntegrationAPI()
- const bankRevenue = bankCore.getRevenueAPI("a")
- const bankWire = bankCore.getWireGatewayAPI("b")
+ const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI(), mockHttpClient)
+ const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a"), "a", mockHttpClient)
+ const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b"), "b", mockHttpClient)
return (
<BackendContextProvider defaultUrl="http://backend">
diff --git a/packages/taler-util/src/http-client/bank-conversion.ts b/packages/taler-util/src/http-client/bank-conversion.ts
index 91d07b11b..ea247ccfc 100644
--- a/packages/taler-util/src/http-client/bank-conversion.ts
+++ b/packages/taler-util/src/http-client/bank-conversion.ts
@@ -39,7 +39,7 @@ import {
codecForCashoutConversionResponse,
codecForConversionBankConfig,
} from "./types.js";
-import { makeBearerTokenAuthHeader } from "./utils.js";
+import { CacheEvictor, makeBearerTokenAuthHeader, nullEvictor } from "./utils.js";
export type TalerBankConversionResultByMethod<
prop extends keyof TalerBankConversionHttpClient,
@@ -48,6 +48,10 @@ export type TalerBankConversionErrorsByMethod<
prop extends keyof TalerBankConversionHttpClient,
> = FailCasesByMethod<TalerBankConversionHttpClient, prop>;
+export enum TalerBankConversionCacheEviction {
+ UPDATE_RATE,
+}
+
/**
* The API is used by the wallets.
*/
@@ -55,12 +59,15 @@ export class TalerBankConversionHttpClient {
public readonly PROTOCOL_VERSION = "0:0:0";
httpLib: HttpRequestLibrary;
+ cacheEvictor: CacheEvictor<TalerBankConversionCacheEviction>;
constructor(
readonly baseUrl: string,
httpClient?: HttpRequestLibrary,
+ cacheEvictor?: CacheEvictor<TalerBankConversionCacheEviction>,
) {
this.httpLib = httpClient ?? createPlatformHttpLib();
+ this.cacheEvictor = cacheEvictor ?? nullEvictor;
}
isCompatible(version: string): boolean {
@@ -195,8 +202,10 @@ export class TalerBankConversionHttpClient {
body,
});
switch (resp.status) {
- case HttpStatusCode.NoContent:
+ case HttpStatusCode.NoContent: {
+ this.cacheEvictor.notifySuccess(TalerBankConversionCacheEviction.UPDATE_RATE);
return opEmptySuccess(resp);
+ }
case HttpStatusCode.Unauthorized:
return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.NotImplemented:
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
index 40e29dcef..4131edb11 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -38,11 +38,6 @@ import {
opSuccessFromHttp,
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,
@@ -66,9 +61,11 @@ import {
codecForWithdrawalPublicInfo,
} from "./types.js";
import {
+ CacheEvictor,
addLongPollingParam,
addPaginationParams,
makeBearerTokenAuthHeader,
+ nullEvictor,
} from "./utils.js";
export type TalerCoreBankResultByMethod<
@@ -78,25 +75,38 @@ export type TalerCoreBankErrorsByMethod<
prop extends keyof TalerCoreBankHttpClient,
> = FailCasesByMethod<TalerCoreBankHttpClient, prop>;
-/**
- * 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 {
+export enum TalerCoreBankCacheEviction {
+ DELELE_ACCOUNT,
+ CREATE_ACCOUNT,
+ UPDATE_ACCOUNT,
+ UPDATE_PASSWORD,
+ CREATE_TRANSACTION,
+ CONFIRM_WITHDRAWAL,
+ ABORT_WITHDRAWAL,
+ CREATE_WITHDRAWAL,
+ CREATE_CASHOUT,
+}
+ /**
+ * 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 {
public readonly PROTOCOL_VERSION = "4:0:0";
httpLib: HttpRequestLibrary;
-
+ cacheEvictor: CacheEvictor<TalerCoreBankCacheEviction>;
constructor(
readonly baseUrl: string,
httpClient?: HttpRequestLibrary,
+ cacheEvictor?: CacheEvictor<TalerCoreBankCacheEviction>,
) {
this.httpLib = httpClient ?? createPlatformHttpLib();
+ this.cacheEvictor = cacheEvictor ?? nullEvictor;
}
isCompatible(version: string): boolean {
@@ -142,8 +152,10 @@ export class TalerCoreBankHttpClient {
},
});
switch (resp.status) {
- case HttpStatusCode.Ok:
+ case HttpStatusCode.Ok: {
+ await this.cacheEvictor.notifySuccess(TalerCoreBankCacheEviction.CREATE_ACCOUNT)
return opSuccessFromHttp(resp, codecForRegisterAccountResponse());
+ }
case HttpStatusCode.BadRequest:
return opKnownHttpFailure(resp.status, resp);
case HttpStatusCode.Unauthorized:
@@ -948,47 +960,47 @@ export class TalerCoreBankHttpClient {
* 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);
+ getIntegrationAPI(): string {
+ return new URL(`taler-integration/`, this.baseUrl).href;
+ // 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(
+ getWireGatewayAPI(username: string): string {
+ return new URL(
`accounts/${username}/taler-wire-gateway/`,
this.baseUrl,
- );
- return new TalerWireGatewayHttpClient(url.href, username, this.httpLib);
+ ).href;
+ // 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);
+ getRevenueAPI(username: string): string {
+ return new URL(`accounts/${username}/taler-revenue/`, this.baseUrl).href;
+ // return new TalerRevenueHttpClient(url.href, username, this.httpLib);
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token
*
*/
- getAuthenticationAPI(username: string): TalerAuthenticationHttpClient {
- const url = new URL(`accounts/${username}/`, this.baseUrl);
- return new TalerAuthenticationHttpClient(url.href, username, this.httpLib);
+ getAuthenticationAPI(username: string): string {
+ return new URL(`accounts/${username}/`, this.baseUrl).href;
+ // return new TalerAuthenticationHttpClient(url.href, username, this.httpLib);
}
/**
* https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token
*
*/
- getConversionInfoAPI(): TalerBankConversionHttpClient {
- const url = new URL(`conversion-info/`, this.baseUrl);
- return new TalerBankConversionHttpClient(url.href, this.httpLib);
+ getConversionInfoAPI(): string {
+ return new URL(`conversion-info/`, this.baseUrl).href;
+ // TalerBankConversionHttpClient
}
}
diff --git a/packages/taler-util/src/http-client/utils.ts b/packages/taler-util/src/http-client/utils.ts
index 7abedae63..2b8920b66 100644
--- a/packages/taler-util/src/http-client/utils.ts
+++ b/packages/taler-util/src/http-client/utils.ts
@@ -65,3 +65,11 @@ export function addLongPollingParam(url: URL, param?: LongPollParams) {
url.searchParams.set("long_poll_ms", String(param.timeoutMs));
}
}
+
+export interface CacheEvictor<T> {
+ notifySuccess: (op: T) => Promise<void>;
+}
+
+export const nullEvictor: CacheEvictor<unknown> = {
+ notifySuccess: () => Promise.resolve()
+}
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 28909facb..74ef9e8e6 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -19,6 +19,7 @@ export * from "./errors.js";
export { fnutil } from "./fnutils.js";
export * from "./helpers.js";
export * from "./http-client/bank-conversion.js";
+export * from "./http-client/authentication.js";
export * from "./http-client/bank-core.js";
export * from "./http-client/bank-integration.js";
export * from "./http-client/bank-revenue.js";