summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-04-04 16:24:55 -0300
committerSebastian <sebasjm@gmail.com>2024-04-04 16:25:08 -0300
commit072ac43b9f69807b8514eb11f8214637561a2573 (patch)
treeb5b464682589f2b80dc4d8f547e9d549a4df353a
parent01838bfcc74a2e4e828885d5ab0d6f64cc96f328 (diff)
downloadwallet-core-072ac43b9f69807b8514eb11f8214637561a2573.tar.gz
wallet-core-072ac43b9f69807b8514eb11f8214637561a2573.tar.bz2
wallet-core-072ac43b9f69807b8514eb11f8214637561a2573.zip
fix some API differences including whatwg-url params
-rw-r--r--packages/aml-backoffice-ui/src/context/config.ts4
-rw-r--r--packages/aml-backoffice-ui/src/pages/Cases.tsx398
-rw-r--r--packages/bank-ui/src/context/config.ts4
-rw-r--r--packages/bank-ui/src/pages/admin/AdminHome.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx10
-rw-r--r--packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx11
-rw-r--r--packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx16
-rw-r--r--packages/merchant-backoffice-ui/src/context/session.ts24
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/bank.ts31
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/instance.test.ts14
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/instance.ts16
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/order.test.ts10
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/order.ts8
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/otp.ts8
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/product.test.ts8
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/product.ts12
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/templates.ts8
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/transfer.test.ts2
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/transfer.ts4
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/webhooks.ts8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx5
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx1
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx20
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx22
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx22
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/accounts/list/index.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/accounts/update/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx1
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx9
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx9
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx4
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx6
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/webhooks/update/index.tsx2
-rw-r--r--packages/merchant-backoffice-ui/src/paths/login/index.tsx39
-rw-r--r--packages/taler-harness/src/index.ts12
-rw-r--r--packages/taler-util/src/http-client/bank-core.ts8
-rw-r--r--packages/taler-util/src/http-client/exchange.ts2
-rw-r--r--packages/taler-util/src/http-client/merchant.ts4
-rw-r--r--packages/taler-util/src/http-client/types.ts24
-rw-r--r--packages/taler-util/src/whatwg-url.ts9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddExchange/index.ts5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts11
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddExchange/views.tsx113
-rw-r--r--packages/web-util/src/context/activity.ts5
-rw-r--r--packages/web-util/src/context/bank-api.ts47
-rw-r--r--packages/web-util/src/context/merchant-api.ts64
-rw-r--r--packages/web-util/src/utils/http-impl.sw.ts5
70 files changed, 638 insertions, 507 deletions
diff --git a/packages/aml-backoffice-ui/src/context/config.ts b/packages/aml-backoffice-ui/src/context/config.ts
index 0ea491ca4..7004225eb 100644
--- a/packages/aml-backoffice-ui/src/context/config.ts
+++ b/packages/aml-backoffice-ui/src/context/config.ts
@@ -65,7 +65,9 @@ export const ExchangeApiProvider = ({
useEffect(() => {
api.getConfig()
.then((resp) => {
- if (api.isCompatible(resp.body.version)) {
+ if (resp.type === "fail") {
+ setChecked({ type: "error", error: TalerError.fromUncheckedDetail(resp.detail) });
+ }else if (api.isCompatible(resp.body.version)) {
setChecked({ type: "ok", config: resp.body });
} else {
setChecked({ type: "incompatible", result: resp.body, supported: api.PROTOCOL_VERSION })
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx
index 88580a4ce..faef0ca54 100644
--- a/packages/aml-backoffice-ui/src/pages/Cases.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -1,168 +1,198 @@
-import { HttpStatusCode, TalerError, TalerExchangeApi, TranslatedString, assertUnreachable } from "@gnu-taler/taler-util";
-import { ErrorLoading, Loading, createNewForm, useTranslationContext } from "@gnu-taler/web-util/browser";
+/*
+ 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 <http://www.gnu.org/licenses/>
+ */
+import {
+ HttpStatusCode,
+ TalerError,
+ TalerExchangeApi,
+ assertUnreachable
+} from "@gnu-taler/taler-util";
+import {
+ ErrorLoading,
+ Loading,
+ createNewForm,
+ useTranslationContext,
+} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { useCases } from "../hooks/useCases.js";
import { Pages } from "../pages.js";
-import { Officer } from "./Officer.js";
import { amlStateConverter } from "../utils/converter.js";
import { AmlExchangeBackend } from "../utils/types.js";
+import { Officer } from "./Officer.js";
-export function CasesUI({ records, filter, onChangeFilter, onFirstPage, onNext }: { onFirstPage?: () => void, onNext?: () => void, filter: AmlExchangeBackend.AmlState, onChangeFilter: (f: AmlExchangeBackend.AmlState) => void, records: TalerExchangeApi.AmlRecord[] }): VNode {
+export function CasesUI({
+ records,
+ filter,
+ onChangeFilter,
+ onFirstPage,
+ onNext,
+}: {
+ onFirstPage?: () => void;
+ onNext?: () => void;
+ filter: AmlExchangeBackend.AmlState;
+ onChangeFilter: (f: AmlExchangeBackend.AmlState) => void;
+ records: TalerExchangeApi.AmlRecord[];
+}): VNode {
const { i18n } = useTranslationContext();
const form = createNewForm<{ state: AmlExchangeBackend.AmlState }>();
- return <div>
- <div class="sm:flex sm:items-center">
- <div class="px-2 sm:flex-auto">
- <h1 class="text-base font-semibold leading-6 text-gray-900">
- <i18n.Translate>
- Cases
- </i18n.Translate>
- </h1>
- <p class="mt-2 text-sm text-gray-700 w-80">
- <i18n.Translate>
- A list of all the account with the status
- </i18n.Translate>
- </p>
- </div>
- <div class="px-2">
- <form.Provider
- initial={{ state: filter }}
- onUpdate={(v) => {
- onChangeFilter(v.state ?? filter);
- }}
- onSubmit={(v) => { }}
- >
- <form.InputChoiceHorizontal
- name="state"
- label={i18n.str`Filter`}
- converter={amlStateConverter}
- choices={[
- {
- label: i18n.str`Pending`,
- value: AmlExchangeBackend.AmlState.pending,
- },
- {
- label: i18n.str`Frozen`,
- value: AmlExchangeBackend.AmlState.frozen,
- },
- {
- label: i18n.str`Normal`,
- value: AmlExchangeBackend.AmlState.normal,
- },
- ]}
- />
-
- </form.Provider>
+ return (
+ <div>
+ <div class="sm:flex sm:items-center">
+ <div class="px-2 sm:flex-auto">
+ <h1 class="text-base font-semibold leading-6 text-gray-900">
+ <i18n.Translate>Cases</i18n.Translate>
+ </h1>
+ <p class="mt-2 text-sm text-gray-700 w-80">
+ <i18n.Translate>
+ A list of all the account with the status
+ </i18n.Translate>
+ </p>
+ </div>
+ <div class="px-2">
+ <form.Provider
+ initial={{ state: filter }}
+ onUpdate={(v) => {
+ onChangeFilter(v.state ?? filter);
+ }}
+ onSubmit={(_v) => {}}
+ >
+ <form.InputChoiceHorizontal
+ name="state"
+ label={i18n.str`Filter`}
+ converter={amlStateConverter}
+ choices={[
+ {
+ label: i18n.str`Pending`,
+ value: AmlExchangeBackend.AmlState.pending,
+ },
+ {
+ label: i18n.str`Frozen`,
+ value: AmlExchangeBackend.AmlState.frozen,
+ },
+ {
+ label: i18n.str`Normal`,
+ value: AmlExchangeBackend.AmlState.normal,
+ },
+ ]}
+ />
+ </form.Provider>
+ </div>
</div>
- </div>
- <div class="mt-8 flow-root">
- <div class="overflow-x-auto">
- {!records.length ? (
- <div>empty result </div>
- ) : (
- <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
- <table class="min-w-full divide-y divide-gray-300">
- <thead>
- <tr>
- <th
- scope="col"
- class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80"
- >
- <i18n.Translate>
- Account Id
- </i18n.Translate>
- </th>
- <th
- scope="col"
- class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
- >
- <i18n.Translate>
- Status
- </i18n.Translate>
- </th>
- <th
- scope="col"
- class="sm:hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
- >
- <i18n.Translate>
- Threshold
- </i18n.Translate>
- </th>
- </tr>
- </thead>
- <tbody class="divide-y divide-gray-200 bg-white">
- {records.map((r) => {
- return (
- <tr class="hover:bg-gray-100 ">
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500 ">
- <div class="text-gray-900">
- <a
- href={Pages.account.url({ account: r.h_payto })}
- class="text-indigo-600 hover:text-indigo-900"
- >
- {r.h_payto.substring(0, 16)}...
- </a>
- </div>
- </td>
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
- {((state: AmlExchangeBackend.AmlState): VNode => {
- switch (state) {
- case AmlExchangeBackend.AmlState.normal: {
- return (
- <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
- Normal
- </span>
- );
- }
- case AmlExchangeBackend.AmlState.pending: {
- return (
- <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20">
- Pending
- </span>
- );
+ <div class="mt-8 flow-root">
+ <div class="overflow-x-auto">
+ {!records.length ? (
+ <div>empty result </div>
+ ) : (
+ <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
+ <table class="min-w-full divide-y divide-gray-300">
+ <thead>
+ <tr>
+ <th
+ scope="col"
+ class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80"
+ >
+ <i18n.Translate>Account Id</i18n.Translate>
+ </th>
+ <th
+ scope="col"
+ class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
+ >
+ <i18n.Translate>Status</i18n.Translate>
+ </th>
+ <th
+ scope="col"
+ class="sm:hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
+ >
+ <i18n.Translate>Threshold</i18n.Translate>
+ </th>
+ </tr>
+ </thead>
+ <tbody class="divide-y divide-gray-200 bg-white">
+ {records.map((r) => {
+ return (
+ <tr key={r.h_payto} class="hover:bg-gray-100 ">
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500 ">
+ <div class="text-gray-900">
+ <a
+ href={Pages.account.url({ account: r.h_payto })}
+ class="text-indigo-600 hover:text-indigo-900"
+ >
+ {r.h_payto.substring(0, 16)}...
+ </a>
+ </div>
+ </td>
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
+ {((state: AmlExchangeBackend.AmlState): VNode => {
+ switch (state) {
+ case AmlExchangeBackend.AmlState.normal: {
+ return (
+ <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
+ Normal
+ </span>
+ );
+ }
+ case AmlExchangeBackend.AmlState.pending: {
+ return (
+ <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20">
+ Pending
+ </span>
+ );
+ }
+ case AmlExchangeBackend.AmlState.frozen: {
+ return (
+ <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20">
+ Frozen
+ </span>
+ );
+ }
}
- case AmlExchangeBackend.AmlState.frozen: {
- return (
- <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20">
- Frozen
- </span>
- );
- }
- }
- })(r.current_state)}
- </td>
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900">
- {r.threshold}
- </td>
- </tr>
- );
- })}
- </tbody>
- </table>
- <Pagination onFirstPage={onFirstPage} onNext={onNext} />
- </div>
- )}
+ })(r.current_state)}
+ </td>
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900">
+ {r.threshold}
+ </td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ <Pagination onFirstPage={onFirstPage} onNext={onNext} />
+ </div>
+ )}
+ </div>
</div>
</div>
- </div>
-
+ );
}
-
export function Cases() {
- const [stateFilter, setStateFilter] = useState(AmlExchangeBackend.AmlState.pending);
+ const [stateFilter, setStateFilter] = useState(
+ AmlExchangeBackend.AmlState.pending,
+ );
const list = useCases(stateFilter);
if (!list) {
- return <Loading />
+ return <Loading />;
}
if (list instanceof TalerError) {
- return <ErrorLoading error={list} />
+ return <ErrorLoading error={list} />;
}
if (list.data.type === "fail") {
@@ -170,34 +200,81 @@ export function Cases() {
case HttpStatusCode.Unauthorized:
case HttpStatusCode.Forbidden:
case HttpStatusCode.NotFound:
- case HttpStatusCode.Conflict: return <Officer />
- default: assertUnreachable(list.data)
+ case HttpStatusCode.Conflict:
+ return <Officer />;
+ default:
+ assertUnreachable(list.data);
}
}
- const { records } = list.data.body
+ const { records } = list.data.body;
- return <CasesUI
- records={records}
- onFirstPage={list.pagination && !list.pagination.isFirstPage ? list.pagination.reset : undefined}
- onNext={list.pagination && !list.pagination.isLastPage ? list.pagination.loadMore : undefined}
- filter={stateFilter}
- onChangeFilter={setStateFilter}
- />
+ return (
+ <CasesUI
+ records={records}
+ onFirstPage={
+ list.pagination && !list.pagination.isFirstPage
+ ? list.pagination.reset
+ : undefined
+ }
+ onNext={
+ list.pagination && !list.pagination.isLastPage
+ ? list.pagination.loadMore
+ : undefined
+ }
+ filter={stateFilter}
+ onChangeFilter={setStateFilter}
+ />
+ );
}
-export const PeopleIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
- <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
-</svg>
+export const PeopleIcon = () => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke-width="1.5"
+ stroke="currentColor"
+ class="w-6 h-6"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
+ />
+ </svg>
+);
-export const HomeIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
- <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
-</svg>
+export const HomeIcon = () => (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke-width="1.5"
+ stroke="currentColor"
+ class="w-6 h-6"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
+ />
+ </svg>
+);
-function Pagination({ onFirstPage, onNext }: { onFirstPage?: () => void, onNext?: () => void, }) {
- const { i18n } = useTranslationContext()
+function Pagination({
+ onFirstPage,
+ onNext,
+}: {
+ onFirstPage?: () => void;
+ onNext?: () => void;
+}) {
+ const { i18n } = useTranslationContext();
return (
- <nav class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg" aria-label="Pagination">
+ <nav
+ class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg"
+ aria-label="Pagination"
+ >
<div class="flex flex-1 justify-between sm:justify-end">
<button
class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0"
@@ -215,6 +292,5 @@ function Pagination({ onFirstPage, onNext }: { onFirstPage?: () => void, onNext?
</button>
</div>
</nav>
-
- )
+ );
}
diff --git a/packages/bank-ui/src/context/config.ts b/packages/bank-ui/src/context/config.ts
index 9522c72bc..342a65c4f 100644
--- a/packages/bank-ui/src/context/config.ts
+++ b/packages/bank-ui/src/context/config.ts
@@ -125,7 +125,9 @@ export const BankCoreApiProvider = ({
bankClient
.getConfig()
.then((resp) => {
- if (bankClient.isCompatible(resp.body.version)) {
+ if (resp.type === "fail") {
+ setChecked({ type: "error", error: TalerError.fromUncheckedDetail(resp.detail) });
+ } else if (bankClient.isCompatible(resp.body.version)) {
setChecked({ type: "ok", config: resp.body, hints: [] });
} else {
// this API supports version 3.0.3
diff --git a/packages/bank-ui/src/pages/admin/AdminHome.tsx b/packages/bank-ui/src/pages/admin/AdminHome.tsx
index 7cdbdb450..acae09b40 100644
--- a/packages/bank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/bank-ui/src/pages/admin/AdminHome.tsx
@@ -31,15 +31,7 @@ import {
} from "@gnu-taler/web-util/browser";
import {
format,
- getDaysInMonth,
- getHours,
- getMonth,
- getYear,
- setDate,
- setHours,
- setMonth,
- setYear,
- sub,
+ sub
} from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
diff --git a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
index cb4442897..2a24dfbe2 100644
--- a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
+++ b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
@@ -20,10 +20,10 @@
*/
import {
- useTranslationContext
+ useMerchantApiContext,
+ useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { useSessionContext } from "../../context/session.js";
import { Entity } from "../../paths/admin/create/CreatePage.js";
import { Input } from "../form/Input.js";
import { InputDuration } from "../form/InputDuration.js";
@@ -42,15 +42,13 @@ export function DefaultInstanceFormFields({
showId: boolean;
}): VNode {
const { i18n } = useTranslationContext();
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
return (
<Fragment>
{showId && (
<InputWithAddon<Entity>
name="id"
- addonBefore={new URL("instances/", backendUrl).href}
+ addonBefore={new URL("instances/", backendUrl.href).href}
readonly={readonlyId}
label={i18n.str`Identifier`}
tooltip={i18n.str`Name of the instance in URLs. The 'default' instance is special in that it is used to administer other instances.`}
diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
index d6a9308bf..9875ce42e 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
@@ -40,12 +40,15 @@ export function Sidebar({ mobile }: Props): VNode {
const { i18n } = useTranslationContext();
const kycStatus = useInstanceKYCDetails();
- const needKYC = kycStatus !== undefined && !(kycStatus instanceof TalerError) && kycStatus.type === "ok" && !!kycStatus.body;
+ const needKYC =
+ kycStatus !== undefined &&
+ !(kycStatus instanceof TalerError) &&
+ kycStatus.type === "ok" &&
+ !!kycStatus.body;
const { state, logOut } = useSessionContext();
const isLoggedIn = state.status === "loggedIn";
const hasToken = isLoggedIn && state.token !== undefined;
- const backendURL = state.backendUrl;
- const { config } = useMerchantApiContext();
+ const { config, url: backendURL } = useMerchantApiContext();
return (
<aside
@@ -212,7 +215,7 @@ export function Sidebar({ mobile }: Props): VNode {
<i class="mdi mdi-web" />
</span>
<span class="menu-item-label">
- {new URL(backendURL).hostname}
+ {backendURL.hostname}
</span>
</div>
</li>
diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
index 468e5f635..781d2de2c 100644
--- a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
+++ b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx
@@ -19,13 +19,14 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { AmountString, TalerMerchantApi } from "@gnu-taler/taler-util";
import {
+ useMerchantApiContext,
useTranslationContext
} from "@gnu-taler/web-util/browser";
import { h } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import * as yup from "yup";
-import { useSessionContext } from "../../context/session.js";
import {
ProductCreateSchema as createSchema,
ProductUpdateSchema as updateSchema,
@@ -38,7 +39,6 @@ import { InputNumber } from "../form/InputNumber.js";
import { InputStock, Stock } from "../form/InputStock.js";
import { InputTaxes } from "../form/InputTaxes.js";
import { InputWithAddon } from "../form/InputWithAddon.js";
-import { AmountString, TalerMerchantApi } from "@gnu-taler/taler-util";
type Entity = TalerMerchantApi.ProductDetail & { product_id: string };
@@ -84,11 +84,11 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
}
}
const hasErrors = Object.keys(errors).some(
- (k) => (errors as any)[k] !== undefined,
+ (k) => (errors as Record<string, unknown>)[k] !== undefined,
);
const submit = useCallback((): Entity | undefined => {
- const stock: Stock = (value as any).stock;
+ const stock = (value).stock;
if (!stock) {
value.total_stock = -1;
@@ -101,7 +101,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
: stock.nextRestock;
value.address = stock.address;
}
- delete (value as any).stock;
+ delete value.stock;
if (typeof value.minimum_age !== "undefined" && value.minimum_age < 1) {
delete value.minimum_age;
@@ -116,9 +116,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
onSubscribe(hasErrors ? undefined : submit);
}, [submit, hasErrors]);
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
const { i18n } = useTranslationContext();
return (
@@ -132,7 +130,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
{alreadyExist ? undefined : (
<InputWithAddon<Entity>
name="product_id"
- addonBefore={new URL("product/", backendUrl).href}
+ addonBefore={new URL("product/", backendUrl.href).href}
label={i18n.str`ID`}
tooltip={i18n.str`product identification to use in URLs (for internal use only)`}
/>
diff --git a/packages/merchant-backoffice-ui/src/context/session.ts b/packages/merchant-backoffice-ui/src/context/session.ts
index 98cb27400..7a5ef33d7 100644
--- a/packages/merchant-backoffice-ui/src/context/session.ts
+++ b/packages/merchant-backoffice-ui/src/context/session.ts
@@ -39,7 +39,6 @@ export type SessionState = LoggedIn | LoggedOut | Expired;
interface LoggedIn {
status: "loggedIn";
- backendUrl: string;
isAdmin: boolean;
instance: string;
token: AccessToken | undefined;
@@ -52,7 +51,6 @@ interface Impersonate {
}
interface Expired {
status: "expired";
- backendUrl: string;
isAdmin: boolean;
instance: string;
token?: undefined;
@@ -60,7 +58,6 @@ interface Expired {
}
interface LoggedOut {
status: "loggedOut";
- backendUrl: string;
instance: string;
isAdmin: boolean;
token?: undefined;
@@ -69,7 +66,6 @@ interface LoggedOut {
export const codecForSessionStateLoggedIn = (): Codec<LoggedIn> =>
buildCodecForObject<LoggedIn>()
.property("status", codecForConstString("loggedIn"))
- .property("backendUrl", codecForString())
.property("instance", codecForString())
.property("impersonate", codecOptional(codecForImpresonate()))
.property("token", codecOptional(codecForString() as Codec<AccessToken>))
@@ -79,7 +75,6 @@ export const codecForSessionStateLoggedIn = (): Codec<LoggedIn> =>
export const codecForSessionStateExpired = (): Codec<Expired> =>
buildCodecForObject<Expired>()
.property("status", codecForConstString("expired"))
- .property("backendUrl", codecForString())
.property("instance", codecForString())
.property("impersonate", codecOptional(codecForImpresonate()))
.property("isAdmin", codecForBoolean())
@@ -88,7 +83,6 @@ export const codecForSessionStateExpired = (): Codec<Expired> =>
export const codecForSessionStateLoggedOut = (): Codec<LoggedOut> =>
buildCodecForObject<LoggedOut>()
.property("status", codecForConstString("loggedOut"))
- .property("backendUrl", codecForString())
.property("instance", codecForString())
.property("isAdmin", codecForBoolean())
.build("SessionState.LoggedOut");
@@ -121,7 +115,6 @@ export const defaultState = (url: URL): SessionState => {
return {
status: "loggedIn",
instance,
- backendUrl: url.href,
isAdmin: instance === DEFAULT_ADMIN_USERNAME,
token: undefined,
impersonate: undefined,
@@ -151,7 +144,7 @@ export interface SessionStateHandler {
* from loggedIn to impersonate
* @param info
*/
- impersonate(info: { instance: string; token?: AccessToken }): void;
+ impersonate(info: { instance: string; baseUrl: URL, token?: AccessToken }): void;
}
const SESSION_STATE_KEY = buildStorageKey(
@@ -169,20 +162,19 @@ export const INSTANCE_ID_LOOKUP = /\/instances\/([^/]*)\/?$/;
* base URL.
*/
export function useSessionContext(): SessionStateHandler {
- const { url } = useMerchantApiContext();
+ const { url: merchantUrl, changeBackend } = useMerchantApiContext();
const { value: state, update } = useLocalStorage(
SESSION_STATE_KEY,
- defaultState(url),
+ defaultState(merchantUrl),
);
return {
state,
logOut() {
- const instance = inferInstanceName(url);
+ const instance = inferInstanceName(merchantUrl);
const nextState: SessionState = {
status: "loggedOut",
- backendUrl: url.href,
instance,
isAdmin: instance === DEFAULT_ADMIN_USERNAME,
};
@@ -196,9 +188,10 @@ export function useSessionContext(): SessionStateHandler {
if (state.impersonate === undefined) {
return;
}
+ const newURL = new URL(`/`, state.impersonate.originalBackendUrl);
+ changeBackend(newURL);
const nextState: SessionState = {
status: "loggedIn",
- backendUrl: state.impersonate.originalBackendUrl,
isAdmin: state.impersonate.originalInstance === DEFAULT_ADMIN_USERNAME,
instance: state.impersonate.originalInstance,
token: state.impersonate.originalToken,
@@ -211,16 +204,15 @@ export function useSessionContext(): SessionStateHandler {
// can't impersonate if not loggedin
return;
}
+ changeBackend(info.baseUrl);
const nextState: SessionState = {
status: "loggedIn",
- backendUrl: new URL(`instances/${info.instance}`, state.backendUrl)
- .href,
isAdmin: info.instance === DEFAULT_ADMIN_USERNAME,
instance: info.instance,
// FIXME: bank and merchant should have consistent behavior
token: info.token?.substring("secret-token:".length) as AccessToken,
impersonate: {
- originalBackendUrl: state.backendUrl,
+ originalBackendUrl: merchantUrl.href,
originalToken: state.token,
originalInstance: state.instance,
},
diff --git a/packages/merchant-backoffice-ui/src/hooks/bank.ts b/packages/merchant-backoffice-ui/src/hooks/bank.ts
index e1f2638ed..513314f17 100644
--- a/packages/merchant-backoffice-ui/src/hooks/bank.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/bank.ts
@@ -17,7 +17,6 @@ import {
useMerchantApiContext
} from "@gnu-taler/web-util/browser";
import { useState } from "preact/hooks";
-import { PAGE_SIZE } from "../utils/constants.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
import { AccessToken, TalerHttpError, TalerMerchantManagementResultByMethod } from "@gnu-taler/taler-util";
@@ -38,12 +37,12 @@ export function revalidateInstanceBankAccounts() {
}
export function useInstanceBankAccounts() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
const [offset, setOffset] = useState<string | undefined>();
async function fetcher([token, bid]: [AccessToken, string]) {
- return await management.listBankAccounts(token, {
+ return await instance.listBankAccounts(token, {
limit: 5,
offset: bid,
order: "dec",
@@ -55,28 +54,6 @@ export function useInstanceBankAccounts() {
TalerHttpError
>([session.token, offset, "listBankAccounts"], fetcher);
- const isLastPage =
- data && data.type === "ok" && data.body.accounts.length <= PAGE_SIZE;
- const isFirstPage = !offset;
-
- const result =
- data && data.type == "ok" ? structuredClone(data.body.accounts) : [];
- if (result.length == PAGE_SIZE + 1) {
- result.pop();
- }
- const pagination = {
- result,
- isLastPage,
- isFirstPage,
- loadNext: () => {
- if (!result.length) return;
- setOffset(result[result.length - 1].h_wire);
- },
- loadFirst: () => {
- setOffset(undefined);
- },
- };
-
if (error) return error;
if (data === undefined) return undefined;
if (data.type !== "ok") return data;
@@ -93,10 +70,10 @@ export function revalidateBankAccountDetails() {
}
export function useBankAccountDetails(h_wire: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([token, wireId]: [AccessToken, string]) {
- return await management.getBankAccountDetails(token, wireId);
+ return await instance.getBankAccountDetails(token, wireId);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/hooks/instance.test.ts b/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
index 64f534a06..f409592b0 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
@@ -20,6 +20,7 @@
*/
import { TalerMerchantApi } from "@gnu-taler/taler-util";
+import { useMerchantApiContext } from "@gnu-taler/web-util/browser";
import * as tests from "@gnu-taler/web-util/testing";
import { expect } from "chai";
import {
@@ -36,7 +37,6 @@ import {
API_UPDATE_CURRENT_INSTANCE_AUTH,
API_UPDATE_INSTANCE_BY_ID,
} from "./urls.js";
-import { useMerchantApiContext } from "@gnu-taler/web-util/browser";
describe("instance api interaction with details", () => {
it("should evict cache when updating an instance", async () => {
@@ -81,7 +81,7 @@ describe("instance api interaction with details", () => {
name: "other_name",
} as TalerMerchantApi.QueryInstancesResponse,
});
- api.management.updateCurrentInstance(undefined, {
+ api.instance.updateCurrentInstance(undefined, {
name: "other_name",
} as TalerMerchantApi.InstanceReconfigurationMessage);
},
@@ -242,7 +242,7 @@ describe("instance api interaction with details", () => {
} as TalerMerchantApi.QueryInstancesResponse,
});
- api.management.updateCurrentInstanceAuthentication(undefined, {
+ api.instance.updateCurrentInstanceAuthentication(undefined, {
method: "external"
});
},
@@ -380,7 +380,7 @@ describe("instance admin api interaction with listing", () => {
},
});
- api.management.createInstance(undefined, {
+ api.instance.createInstance(undefined, {
name: "other_name",
} as TalerMerchantApi.InstanceConfigurationMessage)
},
@@ -470,7 +470,7 @@ describe("instance admin api interaction with listing", () => {
},
});
- api.management.deleteInstance(undefined, "the_id");
+ api.instance.deleteInstance(undefined, "the_id");
},
({ query, api }) => {
expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -628,7 +628,7 @@ describe("instance admin api interaction with listing", () => {
},
});
- api.management.deleteInstance(undefined, "the_id", { purge: true })
+ api.instance.deleteInstance(undefined, "the_id", { purge: true })
},
({ query, api }) => {
expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -712,7 +712,7 @@ describe("instance management api interaction with listing", () => {
},
});
- api.management.updateCurrentInstance(undefined, {
+ api.instance.updateCurrentInstance(undefined, {
name: "other_name",
} as TalerMerchantApi.InstanceConfigurationMessage);
},
diff --git a/packages/merchant-backoffice-ui/src/hooks/instance.ts b/packages/merchant-backoffice-ui/src/hooks/instance.ts
index cc907bd8f..1fa84c9d9 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.ts
@@ -33,10 +33,10 @@ export function revalidateInstanceDetails() {
}
export function useInstanceDetails() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([token]: [AccessToken]) {
- return await management.getCurrentInstanceDetails(token);
+ return await instance.getCurrentInstanceDetails(token);
}
const { data, error } = useSWR<
@@ -58,10 +58,10 @@ export function revalidateInstanceKYCDetails() {
}
export function useInstanceKYCDetails() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([token]: [AccessToken]) {
- return await management.getCurrentIntanceKycStatus(token, {});
+ return await instance.getCurrentIntanceKycStatus(token, {});
}
const { data, error } = useSWR<
@@ -85,10 +85,10 @@ export function revalidateManagedInstanceDetails() {
}
export function useManagedInstanceDetails(instanceId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([token, instanceId]: [AccessToken, string]) {
- return await management.getInstanceDetails(token, instanceId);
+ return await instance.getInstanceDetails(token, instanceId);
}
const { data, error } = useSWR<
@@ -110,10 +110,10 @@ export function revalidateBackendInstances() {
}
export function useBackendInstances() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([token]: [AccessToken]) {
- return await management.listInstances(token);
+ return await instance.listInstances(token);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/hooks/order.test.ts b/packages/merchant-backoffice-ui/src/hooks/order.test.ts
index 243415bdd..1aa2fcf0a 100644
--- a/packages/merchant-backoffice-ui/src/hooks/order.test.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/order.test.ts
@@ -86,7 +86,7 @@ describe("order api interaction with listing", () => {
},
});
- api.management.createOrder(undefined, {
+ api.instance.createOrder(undefined, {
order: { amount: "ARS:12" as AmountString, summary: "pay me" },
})
},
@@ -171,7 +171,7 @@ describe("order api interaction with listing", () => {
},
});
- api.management.addRefund(undefined, "1", {
+ api.instance.addRefund(undefined, "1", {
reason: "double pay",
refund: "EUR:1" as AmountString,
})
@@ -247,7 +247,7 @@ describe("order api interaction with listing", () => {
},
});
- api.management.deleteOrder(undefined, "1")
+ api.instance.deleteOrder(undefined, "1")
},
({ query, api }) => {
expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -316,7 +316,7 @@ describe("order api interaction with details", () => {
} as unknown as TalerMerchantApi.CheckPaymentPaidResponse,
});
- api.management.addRefund(undefined, "1", {
+ api.instance.addRefund(undefined, "1", {
reason: "double pay",
refund: "EUR:1" as AmountString,
})
@@ -386,7 +386,7 @@ describe("order api interaction with details", () => {
} as unknown as TalerMerchantApi.CheckPaymentPaidResponse,
});
- api.management.forgetOrder(undefined, "1", {
+ api.instance.forgetOrder(undefined, "1", {
fields: ["$.summary"],
})
},
diff --git a/packages/merchant-backoffice-ui/src/hooks/order.ts b/packages/merchant-backoffice-ui/src/hooks/order.ts
index 47ddf1c38..b1805f6e3 100644
--- a/packages/merchant-backoffice-ui/src/hooks/order.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/order.ts
@@ -36,10 +36,10 @@ export function revalidateOrderDetails() {
}
export function useOrderDetails(oderId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([dId, token]: [string, AccessToken]) {
- return await management.getOrderDetails(token, dId);
+ return await instance.getOrderDetails(token, dId);
}
const { data, error } = useSWR<
@@ -65,12 +65,12 @@ export function useInstanceOrders(
updatePosition: (d: string | undefined) => void = () => { },
) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
// const [offset, setOffset] = useState<string | undefined>(args?.position);
async function fetcher([token, o, p, r, w, d]: [AccessToken, string, boolean, boolean, boolean, AbsoluteTime]) {
- return await management.listOrders(token, {
+ return await instance.listOrders(token, {
limit: PAGE_SIZE,
offset: o,
order: "dec",
diff --git a/packages/merchant-backoffice-ui/src/hooks/otp.ts b/packages/merchant-backoffice-ui/src/hooks/otp.ts
index 69e4a0f4f..898a27a69 100644
--- a/packages/merchant-backoffice-ui/src/hooks/otp.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/otp.ts
@@ -35,12 +35,12 @@ export function revalidateInstanceOtpDevices() {
}
export function useInstanceOtpDevices() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
const [offset, setOffset] = useState<string | undefined>();
async function fetcher([token, bid]: [AccessToken, string]) {
- return await management.listOtpDevices(token, {
+ return await instance.listOtpDevices(token, {
limit: PAGE_SIZE,
offset: bid,
order: "dec",
@@ -68,10 +68,10 @@ export function revalidateOtpDeviceDetails() {
}
export function useOtpDeviceDetails(deviceId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([dId, token]: [string, AccessToken]) {
- return await management.getOtpDeviceDetails(token, dId);
+ return await instance.getOtpDeviceDetails(token, dId);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/hooks/product.test.ts b/packages/merchant-backoffice-ui/src/hooks/product.test.ts
index 1be00201a..39281241c 100644
--- a/packages/merchant-backoffice-ui/src/hooks/product.test.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/product.test.ts
@@ -99,7 +99,7 @@ describe("product api interaction with listing", () => {
} as TalerMerchantApi.ProductDetail,
});
- api.management.addProduct(undefined, {
+ api.instance.addProduct(undefined, {
price: "ARS:23",
} as any);
},
@@ -187,7 +187,7 @@ describe("product api interaction with listing", () => {
} as TalerMerchantApi.ProductDetail,
});
- api.management.updateProduct(undefined, "1234", {
+ api.instance.updateProduct(undefined, "1234", {
price: "ARS:13",
} as any);
},
@@ -267,7 +267,7 @@ describe("product api interaction with listing", () => {
price: "ARS:12",
} as TalerMerchantApi.ProductDetail,
});
- api.management.deleteProduct(undefined, "2345");
+ api.instance.deleteProduct(undefined, "2345");
},
({ query, api }) => {
expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -337,7 +337,7 @@ describe("product api interaction with details", () => {
} as TalerMerchantApi.ProductDetail,
});
- api.management.updateProduct(undefined, "12", {
+ api.instance.updateProduct(undefined, "12", {
description: "other description",
} as any);
},
diff --git a/packages/merchant-backoffice-ui/src/hooks/product.ts b/packages/merchant-backoffice-ui/src/hooks/product.ts
index 6721136a5..cfbd4a653 100644
--- a/packages/merchant-backoffice-ui/src/hooks/product.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/product.ts
@@ -40,14 +40,14 @@ export function revalidateInstanceProducts() {
}
export function useInstanceProducts() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
const [offset, setOffset] = useState<number | undefined>();
async function fetcher([token, bid]: [AccessToken, number]) {
- const list = await management.listProducts(token, {
+ const list = await instance.listProducts(token, {
limit: PAGE_SIZE,
- offset: String(bid),
+ offset: bid === undefined ? undefined: String(bid),
order: "dec",
});
if (list.type !== "ok") {
@@ -55,7 +55,7 @@ export function useInstanceProducts() {
}
const all: Array<ProductWithId | undefined> = await Promise.all(
list.body.products.map(async (c) => {
- const r = await management.getProductDetails(token, c.product_id);
+ const r = await instance.getProductDetails(token, c.product_id);
if (r.type === "fail") {
return undefined;
}
@@ -89,10 +89,10 @@ export function revalidateProductDetails() {
}
export function useProductDetails(productId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([pid, token]: [string, AccessToken]) {
- return await management.getProductDetails(token, pid);
+ return await instance.getProductDetails(token, pid);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/hooks/templates.ts b/packages/merchant-backoffice-ui/src/hooks/templates.ts
index 10e480b01..dbea93fdf 100644
--- a/packages/merchant-backoffice-ui/src/hooks/templates.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/templates.ts
@@ -39,12 +39,12 @@ export function revalidateInstanceTemplates() {
}
export function useInstanceTemplates() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
const [offset, setOffset] = useState<string | undefined>();
async function fetcher([token, bid]: [AccessToken, string]) {
- return await management.listTemplates(token, {
+ return await instance.listTemplates(token, {
limit: PAGE_SIZE,
offset: bid,
order: "dec",
@@ -73,10 +73,10 @@ export function revalidateProductDetails() {
}
export function useTemplateDetails(templateId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([tid, token]: [string, AccessToken]) {
- return await management.getTemplateDetails(token, tid);
+ return await instance.getTemplateDetails(token, tid);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/hooks/transfer.test.ts b/packages/merchant-backoffice-ui/src/hooks/transfer.test.ts
index b424e9686..d0865d236 100644
--- a/packages/merchant-backoffice-ui/src/hooks/transfer.test.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/transfer.test.ts
@@ -86,7 +86,7 @@ describe("transfer api interaction with listing", () => {
},
});
- api.management.informWireTransfer(undefined, {
+ api.instance.informWireTransfer(undefined, {
wtid: "3",
credit_amount: "EUR:1" as AmountString,
exchange_url: "exchange.url",
diff --git a/packages/merchant-backoffice-ui/src/hooks/transfer.ts b/packages/merchant-backoffice-ui/src/hooks/transfer.ts
index 2810a4cba..44068f52d 100644
--- a/packages/merchant-backoffice-ui/src/hooks/transfer.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/transfer.ts
@@ -43,12 +43,12 @@ export function useInstanceTransfers(
updatePosition: (id: string | undefined) => void = (() => { }),
) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
// const [offset, setOffset] = useState<string | undefined>(args?.position);
async function fetcher([token, o, p, v]: [AccessToken, string, string, boolean]) {
- return await management.listWireTransfers(token, {
+ return await instance.listWireTransfers(token, {
paytoURI: p,
verified: v,
limit: PAGE_SIZE,
diff --git a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
index 5e2e08bcc..c69db6e80 100644
--- a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
@@ -37,12 +37,12 @@ export function revalidateInstanceWebhooks() {
}
export function useInstanceWebhooks() {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
const [offset, setOffset] = useState<string | undefined>();
async function fetcher([token, bid]: [AccessToken, string]) {
- return await management.listWebhooks(token, {
+ return await instance.listWebhooks(token, {
limit: 5,
offset: bid,
order: "dec",
@@ -104,10 +104,10 @@ export function revalidateWebhookDetails() {
}
export function useWebhookDetails(webhookId: string) {
const { state: session } = useSessionContext();
- const { lib: { management } } = useMerchantApiContext();
+ const { lib: { instance } } = useMerchantApiContext();
async function fetcher([hookId, token]: [string, AccessToken]) {
- return await management.getWebhookDetails(token, hookId);
+ return await instance.getWebhookDetails(token, hookId);
}
const { data, error } = useSWR<
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx
index 39fdb6bdc..54d947e14 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/Create.stories.tsx
@@ -19,9 +19,9 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { h, VNode, FunctionalComponent } from "preact";
-import { CreatePage as TestedComponent } from "./CreatePage.js";
import { MerchantApiProviderTesting } from "@gnu-taler/web-util/browser";
+import { FunctionalComponent, h } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
export default {
title: "Pages/Instance/Create",
@@ -40,6 +40,7 @@ function createExample<Props>(
<MerchantApiProviderTesting
value={{
cancelRequest: () => {},
+ changeBackend: () => {},
config: {
currency: "ARS",
version: "1",
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
index 431015d6f..8ee8608a3 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
@@ -54,7 +54,7 @@ export default function Create({ onBack, onConfirm, forceId }: Props): VNode {
) => {
if (state.status !== "loggedIn") return;
try {
- await lib.management.createInstance(state.token, d);
+ await lib.instance.createInstance(state.token, d);
if (d.auth.token) {
//if auth has been updated, request a new access token
const result = await lib.authenticate.createAccessTokenBearer(
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx
index 8166dc739..d4258058b 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/stories.tsx
@@ -40,6 +40,7 @@ function createExample<Props>(
<MerchantApiProviderTesting
value={{
cancelRequest: () => {},
+ changeBackend: () => {},
config: {
currency: "ARS",
version: "1",
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
index a03a2659b..923c095d3 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/TableActive.tsx
@@ -20,7 +20,10 @@
*/
import { TalerMerchantApi } from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import {
+ useMerchantApiContext,
+ useTranslationContext,
+} from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { StateUpdater, useEffect, useState } from "preact/hooks";
import { useSessionContext } from "../../../context/session.js";
@@ -149,7 +152,8 @@ function Table({
onPurge,
}: TableProps): VNode {
const { i18n } = useTranslationContext();
- const { impersonate } = useSessionContext()
+ const { lib } = useMerchantApiContext();
+ const { impersonate } = useSessionContext();
return (
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
@@ -198,10 +202,16 @@ function Table({
</td>
<td>
<a
- href={`#/orders?instance=${i.id}`}
- onClick={(e) => {
- impersonate({instance: i.id});
+ href={`#/orders`}
+ onClick={async (e) => {
e.preventDefault();
+ const newInstanceApi = lib.subInstanceApi(i.id);
+ //not checking /config since this comes from instance list
+ impersonate({
+ instance: i.id,
+ baseUrl: new URL(newInstanceApi.instance.baseUrl),
+ token: undefined,
+ });
}}
>
{i.id}
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
index f26ff8935..7bf64cdbb 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
@@ -91,7 +91,7 @@ export default function Instances({
return;
}
try {
- await lib.management.deleteInstance(state.token, deleting.id);
+ await lib.instance.deleteInstance(state.token, deleting.id);
// pushNotification({message: 'delete_success', type: 'SUCCESS' })
setNotif({
message: i18n.str`Instance "${deleting.name}" (ID: ${deleting.id}) has been deleted`,
@@ -118,7 +118,7 @@ export default function Instances({
return;
}
try {
- await lib.management.deleteInstance(state.token, purging.id, { purge: true });
+ await lib.instance.deleteInstance(state.token, purging.id, { purge: true });
setNotif({
message: i18n.str`Instance '${purging.name}' (ID: ${purging.id}) has been disabled`,
type: "SUCCESS",
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx
index 0ce126b76..3d27b9a1a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx
@@ -46,7 +46,7 @@ export default function CreateValidator({ onConfirm, onBack }: Props): VNode {
<CreatePage
onBack={onBack}
onCreate={(request: Entity) => {
- return api.management.addBankAccount(state.token, request)
+ return api.instance.addBankAccount(state.token, request)
.then(() => {
onConfirm()
})
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx
index 50cf0fe70..4ee68cd80 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx
@@ -24,12 +24,12 @@ import { h, VNode } from "preact";
import { CardTable } from "./Table.js";
export interface Props {
- devices: TalerMerchantApi.BankAccountEntry[];
- onLoadMoreBefore?: () => void;
- onLoadMoreAfter?: () => void;
+ devices: TalerMerchantApi.BankAccountSummaryEntry[];
+ // onLoadMoreBefore?: () => void;
+ // onLoadMoreAfter?: () => void;
onCreate: () => void;
- onDelete: (e: TalerMerchantApi.BankAccountEntry) => void;
- onSelect: (e: TalerMerchantApi.BankAccountEntry) => void;
+ onDelete: (e: TalerMerchantApi.BankAccountSummaryEntry) => void;
+ onSelect: (e: TalerMerchantApi.BankAccountSummaryEntry) => void;
}
export function ListPage({
@@ -37,8 +37,8 @@ export function ListPage({
onCreate,
onDelete,
onSelect,
- onLoadMoreBefore,
- onLoadMoreAfter,
+ // onLoadMoreBefore,
+ // onLoadMoreAfter,
}: Props): VNode {
return (
@@ -51,10 +51,10 @@ export function ListPage({
onCreate={onCreate}
onDelete={onDelete}
onSelect={onSelect}
- onLoadMoreBefore={onLoadMoreBefore}
- hasMoreBefore={!onLoadMoreBefore}
- onLoadMoreAfter={onLoadMoreAfter}
- hasMoreAfter={!onLoadMoreAfter}
+ // onLoadMoreBefore={onLoadMoreBefore}
+ // hasMoreBefore={!onLoadMoreBefore}
+ // onLoadMoreAfter={onLoadMoreAfter}
+ // hasMoreAfter={!onLoadMoreAfter}
/>
</section>
);
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx
index 690e3a2fc..efe484402 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx
@@ -24,17 +24,13 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { StateUpdater, useState } from "preact/hooks";
-type Entity = TalerMerchantApi.BankAccountEntry;
+type Entity = TalerMerchantApi.BankAccountSummaryEntry;
interface Props {
accounts: Entity[];
onDelete: (e: Entity) => void;
onSelect: (e: Entity) => void;
onCreate: () => void;
- onLoadMoreBefore?: () => void;
- hasMoreBefore?: boolean;
- hasMoreAfter?: boolean;
- onLoadMoreAfter?: () => void;
}
export function CardTable({
@@ -42,10 +38,6 @@ export function CardTable({
onCreate,
onDelete,
onSelect,
- onLoadMoreAfter,
- onLoadMoreBefore,
- hasMoreAfter,
- hasMoreBefore,
}: Props): VNode {
const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
@@ -83,10 +75,6 @@ export function CardTable({
onSelect={onSelect}
rowSelection={rowSelection}
rowSelectionHandler={rowSelectionHandler}
- onLoadMoreAfter={onLoadMoreAfter}
- onLoadMoreBefore={onLoadMoreBefore}
- hasMoreAfter={hasMoreAfter}
- hasMoreBefore={hasMoreBefore}
/>
) : (
<EmptyTable />
@@ -103,20 +91,12 @@ interface TableProps {
onDelete: (e: Entity) => void;
onSelect: (e: Entity) => void;
rowSelectionHandler: StateUpdater<string[]>;
- onLoadMoreBefore?: () => void;
- hasMoreBefore?: boolean;
- hasMoreAfter?: boolean;
- onLoadMoreAfter?: () => void;
}
function Table({
accounts,
- onLoadMoreAfter,
onDelete,
onSelect,
- onLoadMoreBefore,
- hasMoreAfter,
- hasMoreBefore,
}: TableProps): VNode {
const { i18n } = useTranslationContext();
const emptyList: Record<PaytoType | "unknown", { parsed: PaytoUri, acc: Entity }[]> = { "bitcoin": [], "x-taler-bank": [], "iban": [], "unknown": [], }
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/index.tsx
index a9454cd07..ccfab3c45 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/index.tsx
@@ -81,16 +81,16 @@ export default function ListOtpDevices({
}
<ListPage
devices={result.body}
- onLoadMoreBefore={
- result.isFirstPage ? undefined: result.loadFirst
- }
- onLoadMoreAfter={result.isLastPage ? undefined : result.loadNext}
+ // onLoadMoreBefore={
+ // result.isFirstPage ? undefined: result.loadFirst
+ // }
+ // onLoadMoreAfter={result.isLastPage ? undefined : result.loadNext}
onCreate={onCreate}
onSelect={(e) => {
onSelect(e.h_wire);
}}
- onDelete={(e: TalerMerchantApi.BankAccountEntry) => {
- return api.management.deleteBankAccount(state.token, e.h_wire)
+ onDelete={(e: TalerMerchantApi.BankAccountSummaryEntry) => {
+ return api.instance.deleteBankAccount(state.token, e.h_wire)
.then(() =>
setNotif({
message: i18n.str`bank account delete successfully`,
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/index.tsx
index 97610e96b..6b8af50a9 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/index.tsx
@@ -80,7 +80,7 @@ export default function UpdateValidator({
account={{ ...result.body, id: bid }}
onBack={onBack}
onUpdate={(data) => {
- return api.management.updateBankAccount(state.token, bid, data)
+ return api.instance.updateBankAccount(state.token, bid, data)
.then(onConfirm)
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
index bb1ee944b..76e3bf878 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
@@ -77,7 +77,7 @@ export default function Detail({
return
}
try {
- await lib.management.deleteCurrentInstance(state.token);
+ await lib.instance.deleteCurrentInstance(state.token);
onDelete();
} catch (error) {
//FIXME: show message error
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx
index 6914b7432..42cb1cb02 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx
@@ -40,6 +40,7 @@ function createExample<Props>(
<MerchantApiProviderTesting
value={{
cancelRequest: () => { },
+ changeBackend: () => { },
config: {
currency: "ARS",
version: "1",
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
index f612389fe..849711df6 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
@@ -94,7 +94,7 @@ export default function OrderCreate({
<CreatePage
onBack={onBack}
onCreate={(request: TalerMerchantApi.PostOrderRequest) => {
- lib.management.createOrder(state.token, request)
+ lib.instance.createOrder(state.token, request)
.then((r) => {
if (r.type === "ok") {
return onConfirm(r.body.order_id)
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
index 4ed78b002..4afc40285 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
@@ -25,7 +25,7 @@ import {
TalerMerchantApi,
stringifyRefundUri,
} from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { useMerchantApiContext, useTranslationContext } from "@gnu-taler/web-util/browser";
import { format, formatDistance } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
@@ -38,7 +38,6 @@ import { InputGroup } from "../../../../components/form/InputGroup.js";
import { InputLocation } from "../../../../components/form/InputLocation.js";
import { TextField } from "../../../../components/form/TextField.js";
import { ProductList } from "../../../../components/product/ProductList.js";
-import { useSessionContext } from "../../../../context/session.js";
import {
datetimeFormatForSettings,
usePreference,
@@ -427,12 +426,10 @@ function PaidPage({
});
const [value, valueHandler] = useState<Partial<Paid>>(order);
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
const refundurl = stringifyRefundUri({
- merchantBaseUrl: backendUrl,
+ merchantBaseUrl: backendUrl.href,
orderId: order.contract_terms.order_id,
});
const refundable =
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
index b232a146b..4785c795d 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
@@ -84,7 +84,7 @@ export default function Update({ oid, onBack }: Props): VNode {
if (state.status !== "loggedIn") {
return;
}
- api.management
+ api.instance
.addRefund(state.token, id, value)
.then(() =>
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
index 165ced3dc..217eb998a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
@@ -110,7 +110,7 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode {
<JumpToElementById
testIfExist={async (order) => {
- const resp = await lib.management.getOrderDetails(state.token, order);
+ const resp = await lib.instance.getOrderDetails(state.token, order);
return resp.type === "ok";
}}
onSelect={onSelect}
@@ -135,7 +135,7 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode {
jumpToDate={filter.date}
onSelectDate={setNewDate}
onCopyURL={async (id) => {
- const resp = await lib.management.getOrderDetails(state.token, id);
+ const resp = await lib.instance.getOrderDetails(state.token, id);
if (resp.type === "ok") {
if (resp.body.order_status === "unpaid") {
copyToClipboard(resp.body.taler_pay_uri);
@@ -161,7 +161,7 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode {
id={orderToBeRefunded.order_id}
onCancel={() => setOrderToBeRefunded(undefined)}
onConfirm={(value) => {
- lib.management
+ lib.instance
.addRefund(state.token, orderToBeRefunded.order_id, value)
.then(() =>
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
index b1b4a0cf7..982132057 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
@@ -15,7 +15,7 @@
*/
import { TalerMerchantApi } from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { useMerchantApiContext, useTranslationContext } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { QR } from "../../../../components/exception/QR.js";
import { CreatedSuccessfully as Template } from "../../../../components/notifications/CreatedSuccessfully.js";
@@ -33,11 +33,9 @@ export function CreatedSuccessfully({
onConfirm,
}: Props): VNode {
const { i18n } = useTranslationContext();
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
const { state } = useSessionContext();
- const issuer = backendUrl;
+ const issuer = backendUrl.href;
const qrText = `otpauth://totp/${state.instance}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key}`;
const qrTextSafe = `otpauth://totp/${state.instance}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key.substring(0, 6)}...`;
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
index 6ad1295ed..864190c9f 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
@@ -52,7 +52,7 @@ export default function CreateValidator({ onConfirm, onBack }: Props): VNode {
<CreatePage
onBack={onBack}
onCreate={(request: Entity) => {
- return api.management.addOtpDevice(state.token, request)
+ return api.instance.addOtpDevice(state.token, request)
.then((d) => {
setCreated(request)
})
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
index 6b3eded17..324207f59 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
@@ -85,7 +85,7 @@ export default function ListOtpDevices({ onCreate, onSelect }: Props): VNode {
onSelect(e.otp_device_id);
}}
onDelete={(e: TalerMerchantApi.OtpDeviceEntry) => {
- return lib.management
+ return lib.instance
.deleteOtpDevice(state.token, e.otp_device_id)
.then(() =>
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
index 4dc3ec67f..5e34e4c8a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
@@ -98,7 +98,7 @@ export default function UpdateValidator({
}}
onBack={onBack}
onUpdate={async (newInfo) => {
- return lib.management
+ return lib.instance
.updateOtpDevice(state.token, vid, newInfo)
.then((d) => {
if (d.type === "ok") {
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx
index 6cb083025..e1e3c846a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/products/create/index.tsx
@@ -45,7 +45,7 @@ export default function CreateProduct({ onConfirm, onBack }: Props): VNode {
<CreatePage
onBack={onBack}
onCreate={(request: TalerMerchantApi.ProductAddDetail) => {
- return lib.management.addProduct(state.token, request)
+ return lib.instance.addProduct(state.token, request)
.then(() => onConfirm())
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
index 73c221662..dfd633150 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
@@ -81,7 +81,7 @@ export default function ProductList({
<JumpToElementById
testIfExist={async (id) => {
- const resp = await lib.management.getProductDetails(state.token, id);
+ const resp = await lib.instance.getProductDetails(state.token, id);
return resp.type === "ok";
}}
onSelect={onSelect}
@@ -94,7 +94,7 @@ export default function ProductList({
onCreate={onCreate}
onUpdate={async (id, prod) => {
try {
- await lib.management.updateProduct(state.token, id, prod);
+ await lib.instance.updateProduct(state.token, id, prod);
setNotif({
message: i18n.str`product updated successfully`,
type: "SUCCESS",
@@ -123,7 +123,7 @@ export default function ProductList({
onCancel={() => setDeleting(null)}
onConfirm={async (): Promise<void> => {
try {
- await lib.management.deleteProduct(state.token, deleting.id);
+ await lib.instance.deleteProduct(state.token, deleting.id);
setNotif({
message: i18n.str`Product "${deleting.description}" (ID: ${deleting.id}) has been deleted`,
type: "SUCCESS",
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx
index 08b169610..06f813b14 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/products/update/index.tsx
@@ -79,7 +79,7 @@ export default function UpdateProduct({
product={{ ...result.body, product_id: pid }}
onBack={onBack}
onUpdate={(data) => {
- return lib.management.updateProduct(state.token, pid, data)
+ return lib.instance.updateProduct(state.token, pid, data)
.then(onConfirm)
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
index 82c0d0e53..2ba637f44 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
@@ -28,6 +28,7 @@ import {
assertUnreachable,
} from "@gnu-taler/taler-util";
import {
+ useMerchantApiContext,
useTranslationContext
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
@@ -44,7 +45,6 @@ import { InputNumber } from "../../../../components/form/InputNumber.js";
import { InputSearchOnList } from "../../../../components/form/InputSearchOnList.js";
import { InputTab } from "../../../../components/form/InputTab.js";
import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
-import { useSessionContext } from "../../../../context/session.js";
import { useInstanceOtpDevices } from "../../../../hooks/otp.js";
enum Steps {
@@ -73,9 +73,7 @@ interface Props {
export function CreatePage({ onCreate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
const devices = useInstanceOtpDevices();
const [state, setState] = useState<Partial<Entity>>({
@@ -201,7 +199,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
>
<InputWithAddon<Entity>
name="id"
- help={new URL(`templates/${state.id ?? ""}`, backendUrl).href}
+ help={new URL(`templates/${state.id ?? ""}`, backendUrl.href).href}
label={i18n.str`Identifier`}
tooltip={i18n.str`Name of the template in URLs.`}
/>
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx
index d23afb609..f71ca4794 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/index.tsx
@@ -46,7 +46,7 @@ export default function CreateTransfer({ onConfirm, onBack }: Props): VNode {
<CreatePage
onBack={onBack}
onCreate={(request: TalerMerchantApi.TemplateAddDetails) => {
- return lib.management.addTemplate(state.token, request)
+ return lib.instance.addTemplate(state.token, request)
.then(() => onConfirm())
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
index 23bc95943..f9ab6678b 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
@@ -85,7 +85,7 @@ export default function ListTemplates({
<JumpToElementById
testIfExist={async (id) => {
- const resp = await lib.management.getTemplateDetails(state.token, id)
+ const resp = await lib.instance.getTemplateDetails(state.token, id)
return resp.type === "ok"
}}
onSelect={onSelect}
@@ -124,7 +124,7 @@ export default function ListTemplates({
onCancel={() => setDeleting(null)}
onConfirm={async (): Promise<void> => {
try {
- await lib.management.deleteTemplate(state.token, deleting.template_id);
+ await lib.instance.deleteTemplate(state.token, deleting.template_id);
setNotif({
message: i18n.str`Template "${deleting.template_description}" (ID: ${deleting.template_id}) has been deleted`,
type: "SUCCESS",
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
index d48e5e956..0749f45d3 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
@@ -33,7 +33,6 @@ import {
} from "../../../../components/form/FormProvider.js";
import { Input } from "../../../../components/form/Input.js";
import { InputCurrency } from "../../../../components/form/InputCurrency.js";
-import { useSessionContext } from "../../../../context/session.js";
type Entity = TalerMerchantApi.UsingTemplateDetails;
@@ -45,10 +44,7 @@ interface Props {
export function QrPage({ contract, id: templateId, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
- const {
- state: { backendUrl },
- } = useSessionContext();
- const { config } = useMerchantApiContext();
+ const { config, url: backendUrl } = useMerchantApiContext();
const [state, setState] = useState<Partial<Entity>>({
amount: contract.amount,
@@ -73,7 +69,7 @@ export function QrPage({ contract, id: templateId, onBack }: Props): VNode {
templateParams.summary = state.summary ?? "";
}
- const merchantBaseUrl = backendUrl;
+ const merchantBaseUrl = backendUrl.href;
const payTemplateUri = stringifyPayTemplateUri({
merchantBaseUrl,
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
index cf1c13fc4..e1493a870 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
@@ -27,7 +27,7 @@ import {
TalerMerchantApi,
assertUnreachable
} from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { useMerchantApiContext, useTranslationContext } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
@@ -41,7 +41,6 @@ import { InputDuration } from "../../../../components/form/InputDuration.js";
import { InputNumber } from "../../../../components/form/InputNumber.js";
import { InputSearchOnList } from "../../../../components/form/InputSearchOnList.js";
import { InputTab } from "../../../../components/form/InputTab.js";
-import { useSessionContext } from "../../../../context/session.js";
import { useInstanceOtpDevices } from "../../../../hooks/otp.js";
enum Steps {
@@ -68,9 +67,7 @@ interface Props {
export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
- const {
- state: { backendUrl },
- } = useSessionContext();
+ const { url: backendUrl } = useMerchantApiContext();
const intialStep =
@@ -190,7 +187,7 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
<div class="level-left">
<div class="level-item">
<span class="is-size-4">
- {new URL(`templates/${template.otp_id}`,backendUrl).href}
+ {new URL(`templates/${template.otp_id}`,backendUrl.href).href}
</span>
</div>
</div>
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx
index 5fc8bee93..2c0c358e2 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx
@@ -82,7 +82,7 @@ export default function UpdateTemplate({
template={result.body}
onBack={onBack}
onUpdate={(data) => {
- return lib.management.updateTemplate(state.token, tid, data)
+ return lib.instance.updateTemplate(state.token, tid, data)
.then(onConfirm)
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
index d631cef96..46d4da8d7 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
@@ -83,7 +83,7 @@ export default function TemplateUsePage({
request: TalerMerchantApi.UsingTemplateDetails,
) => {
- return lib.management.useTemplateCreateOrder(tid, request)
+ return lib.instance.useTemplateCreateOrder(tid, request)
.then((res) => {
if (res.type === "ok") {
onOrderCreated(res.body.order_id)
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
index 768e21325..cc8f7f9e8 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -70,7 +70,7 @@ export default function Token({
hasToken={hasToken}
onClearToken={async (currentToken): Promise<void> => {
try {
- await lib.management.updateCurrentInstanceAuthentication(currentToken, {
+ await lib.instance.updateCurrentInstanceAuthentication(currentToken, {
method: "external",
})
onChange();
@@ -86,7 +86,7 @@ export default function Token({
}}
onNewToken={async (currentToken, newToken): Promise<void> => {
try {
- await lib.management.updateCurrentInstanceAuthentication(currentToken, {
+ await lib.instance.updateCurrentInstanceAuthentication(currentToken, {
token: newToken,
method: "token"
})
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx
index 35389f5f5..4a92c1178 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx
@@ -56,7 +56,7 @@ export default function CreateTransfer({ onConfirm, onBack }: Props): VNode {
onBack={onBack}
accounts={accounts}
onCreate={(request: TalerMerchantApi.TransferInformation) => {
- return lib.management
+ return lib.instance
.informWireTransfer(state.token, request)
.then(() => onConfirm())
.catch((error) => {
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
index b5319bc2d..4afc400f8 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
@@ -45,15 +45,15 @@ export interface Props {
export default function Update(props: Props): VNode {
const { lib } = useMerchantApiContext();
- const updateInstance = lib.management.updateCurrentInstance.bind(lib.management)
+ const updateInstance = lib.instance.updateCurrentInstance.bind(lib.instance)
const result = useInstanceDetails();
return CommonUpdate(props, result, updateInstance,);
}
export function AdminUpdate(props: Props & { instanceId: string }): VNode {
const { lib } = useMerchantApiContext();
- const t = lib.instance(props.instanceId)
- const updateInstance = lib.instance(props.instanceId).updateCurrentInstance.bind(t)
+ const t = lib.subInstanceApi(props.instanceId).instance;
+ const updateInstance = t.updateCurrentInstance.bind(t)
const result = useManagedInstanceDetails(props.instanceId);
return CommonUpdate(props, result, updateInstance,);
}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/index.tsx
index 50c431079..e4d260b04 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/index.tsx
@@ -46,7 +46,7 @@ export default function CreateWebhook({ onConfirm, onBack }: Props): VNode {
<CreatePage
onBack={onBack}
onCreate={(request: TalerMerchantApi.WebhookAddDetails) => {
- return lib.management.addWebhook(state.token, request)
+ return lib.instance.addWebhook(state.token, request)
.then(() => onConfirm())
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/index.tsx
index 102aef96e..6c68bc973 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/index.tsx
@@ -84,7 +84,7 @@ export default function ListWebhooks({ onCreate, onSelect }: Props): VNode {
onSelect(e.webhook_id);
}}
onDelete={(e: TalerMerchantApi.WebhookEntry) => {
- return lib.management
+ return lib.instance
.deleteWebhook(state.token, e.webhook_id)
.then(() =>
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/update/index.tsx
index 262e5bba4..1253cd9a2 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/update/index.tsx
@@ -82,7 +82,7 @@ export default function UpdateWebhook({
webhook={{ ...result.body, id: tid }}
onBack={onBack}
onUpdate={(data) => {
- return lib.management.updateWebhook(state.token, tid, data)
+ return lib.instance.updateWebhook(state.token, tid, data)
.then(onConfirm)
.catch((error) => {
setNotif({
diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
index 86ec9a9e6..30b5c37bd 100644
--- a/packages/merchant-backoffice-ui/src/paths/login/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
@@ -19,9 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import {
- HttpStatusCode
-} from "@gnu-taler/taler-util";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
import {
useMerchantApiContext,
useTranslationContext,
@@ -29,12 +27,10 @@ import {
import { ComponentChildren, Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { NotificationCard } from "../../components/menu/index.js";
-import {
- useSessionContext
-} from "../../context/session.js";
+import { useSessionContext } from "../../context/session.js";
import { Notification } from "../../utils/types.js";
-interface Props { }
+interface Props {}
const tokenRequest = {
scope: "write",
@@ -47,18 +43,30 @@ const tokenRequest = {
export function LoginPage(_p: Props): VNode {
const [token, setToken] = useState("");
const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const { state, logIn } = useSessionContext();
+ const { state, logIn, impersonate } = useSessionContext();
const { lib } = useMerchantApiContext();
const { i18n } = useTranslationContext();
async function doImpersonateImpl(instanceId: string) {
- const result = await lib
- .impersonate(instanceId)
- .createAccessTokenBearer(token, tokenRequest);
+ const newInstanceApi = lib.subInstanceApi(instanceId);
+ const cfg = await newInstanceApi.instance.getConfig();
+ if (cfg.type !== "ok") {
+ setNotif({
+ message: "Could not load the configuration of this instance.",
+ description: newInstanceApi.instance.baseUrl,
+ type: "ERROR",
+ });
+ return;
+ }
+ const result = await newInstanceApi.authenticate.createAccessTokenBearer(
+ token,
+ tokenRequest,
+ );
+
if (result.type === "ok") {
const { token } = result.body;
- logIn({ token });
+ impersonate({ instance: instanceId, baseUrl: new URL(newInstanceApi.instance.baseUrl), token });
return;
} else {
switch (result.case) {
@@ -126,7 +134,8 @@ export function LoginPage(_p: Props): VNode {
>
<p>
<i18n.Translate>
- Need the access token for the instance <b>"{state.instance}"</b>
+ Need the access token for the instance{" "}
+ <b>"{state.instance}"</b>
</i18n.Translate>
</p>
<div class="field is-horizontal">
@@ -190,7 +199,9 @@ export function LoginPage(_p: Props): VNode {
class="modal-card-body"
style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
>
- <i18n.Translate>Please enter your access token for <b>"{state.instance}"</b>.</i18n.Translate>
+ <i18n.Translate>
+ Please enter your access token for <b>"{state.instance}"</b>.
+ </i18n.Translate>
<div class="field is-horizontal">
<div class="field-label is-normal">
diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts
index 727c3b674..5f2708b85 100644
--- a/packages/taler-harness/src/index.ts
+++ b/packages/taler-harness/src/index.ts
@@ -653,6 +653,12 @@ deploymentCli
const bc = await bank.getConfig()
+ if (bc.type === "fail") {
+ logger.error(
+ `couldn't get bank config. ${bc.detail.hint}`,
+ );
+ return;
+ }
if (!bank.isCompatible(bc.body.version)) {
logger.error(
`bank server version is not compatible: ${bc.body.version}, client version: ${bank.PROTOCOL_VERSION}`,
@@ -660,6 +666,12 @@ deploymentCli
return;
}
const mc = await merchantManager.getConfig()
+ if (mc.type === "fail") {
+ logger.error(
+ `couldn't get merchant config. ${mc.detail.hint}`,
+ );
+ return;
+ }
if (!merchantManager.isCompatible(mc.body.version)) {
logger.error(
`merchant server version is not compatible: ${mc.body.version}, client version: ${merchantManager.PROTOCOL_VERSION}`,
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
index b89ac8af6..59698a68b 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -128,6 +128,8 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok:
return opSuccessFromHttp(resp, codecForCoreBankConfig());
+ case HttpStatusCode.NotFound:
+ return opKnownHttpFailure(resp.status, resp);
default:
return opUnknownFailure(resp, await readTalerErrorResponse(resp));
}
@@ -146,9 +148,9 @@ export class TalerCoreBankHttpClient {
body: TalerCorebankApi.RegisterAccountRequest,
) {
const url = new URL(`accounts`, this.baseUrl);
- const headers: Record<string, string> = {}
+ const headers: Record<string, string> = {};
if (auth) {
- headers.Authorization = makeBearerTokenAuthHeader(auth)
+ headers.Authorization = makeBearerTokenAuthHeader(auth);
}
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
@@ -936,7 +938,7 @@ export class TalerCoreBankHttpClient {
);
}
if (params.date) {
- const {t_s: seconds} = AbsoluteTime.toProtocolTimestamp(params.date)
+ const { t_s: seconds } = AbsoluteTime.toProtocolTimestamp(params.date);
if (seconds !== "never") {
url.searchParams.set("date_s", String(seconds));
}
diff --git a/packages/taler-util/src/http-client/exchange.ts b/packages/taler-util/src/http-client/exchange.ts
index befde4d20..ea7f44cf9 100644
--- a/packages/taler-util/src/http-client/exchange.ts
+++ b/packages/taler-util/src/http-client/exchange.ts
@@ -71,6 +71,8 @@ export class TalerExchangeHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok:
return opSuccessFromHttp(resp, codecForExchangeConfig());
+ case HttpStatusCode.NotFound:
+ return opKnownHttpFailure(resp.status, resp);
default:
return opUnknownFailure(resp, await readTalerErrorResponse(resp));
}
diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts
index 7d80cacb5..cfe3155d1 100644
--- a/packages/taler-util/src/http-client/merchant.ts
+++ b/packages/taler-util/src/http-client/merchant.ts
@@ -127,6 +127,8 @@ export class TalerMerchantInstanceHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok:
return opSuccessFromHttp(resp, codecForMerchantConfig());
+ case HttpStatusCode.NotFound:
+ return opKnownHttpFailure(resp.status, resp);
default:
return opUnknownFailure(resp, await readTalerErrorResponse(resp));
}
@@ -1677,7 +1679,7 @@ export class TalerMerchantInstanceHttpClient {
});
switch (resp.status) {
- case HttpStatusCode.NoContent:
+ case HttpStatusCode.Ok:
return opSuccessFromHttp(resp, codecForWebhookSummaryResponse());
case HttpStatusCode.Unauthorized: // FIXME: missing in docs
return opKnownHttpFailure(resp.status, resp);
diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts
index 8037b5a16..dd2161deb 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -524,17 +524,24 @@ export const codecForAccountAddResponse =
export const codecForAccountsSummaryResponse =
(): Codec<TalerMerchantApi.AccountsSummaryResponse> =>
buildCodecForObject<TalerMerchantApi.AccountsSummaryResponse>()
- .property("accounts", codecForList(codecForBankAccountEntry()))
+ .property("accounts", codecForList(codecForBankAccountSummaryEntry()))
.build("TalerMerchantApi.AccountsSummaryResponse");
+export const codecForBankAccountSummaryEntry =
+ (): Codec<TalerMerchantApi.BankAccountSummaryEntry> =>
+ buildCodecForObject<TalerMerchantApi.BankAccountSummaryEntry>()
+ .property("payto_uri", codecForPaytoString())
+ .property("h_wire", codecForString())
+ .build("TalerMerchantApi.BankAccountSummaryEntry");
+
export const codecForBankAccountEntry =
(): Codec<TalerMerchantApi.BankAccountEntry> =>
buildCodecForObject<TalerMerchantApi.BankAccountEntry>()
.property("payto_uri", codecForPaytoString())
.property("h_wire", codecForString())
.property("salt", codecForString())
- .property("credit_facade_url", codecForURL())
- .property("active", codecForBoolean())
+ .property("credit_facade_url", codecOptional(codecForURL()))
+ .property("active", codecOptional(codecForBoolean()))
.build("TalerMerchantApi.BankAccountEntry");
export const codecForInventorySummaryResponse =
@@ -3772,7 +3779,14 @@ export namespace TalerMerchantApi {
export interface AccountsSummaryResponse {
// List of accounts that are known for the instance.
- accounts: BankAccountEntry[];
+ accounts: BankAccountSummaryEntry[];
+ }
+ export interface BankAccountSummaryEntry {
+ // payto:// URI of the account.
+ payto_uri: PaytoString;
+
+ // Hash over the wire details (including over the salt).
+ h_wire: HashCode;
}
export interface BankAccountEntry {
// payto:// URI of the account.
@@ -3790,7 +3804,7 @@ export namespace TalerMerchantApi {
// true if this account is active,
// false if it is historic.
- active: boolean;
+ active?: boolean;
}
export interface ProductAddDetail {
diff --git a/packages/taler-util/src/whatwg-url.ts b/packages/taler-util/src/whatwg-url.ts
index 991528ae6..13abf5397 100644
--- a/packages/taler-util/src/whatwg-url.ts
+++ b/packages/taler-util/src/whatwg-url.ts
@@ -1908,15 +1908,22 @@ function parseURL(
}
export class URLImpl {
- constructor(url: string, base?: string) {
+ //Include URL type for "url" and "base" params.
+ constructor(url: string | URL, base?: string | URL) {
let parsedBase = null;
if (base !== undefined) {
+ if (base instanceof URL) {
+ base = base.href;
+ }
parsedBase = basicURLParse(base);
if (parsedBase === null) {
throw new TypeError(`Invalid base URL: ${base}`);
}
}
+ if (url instanceof URL) {
+ url = url.href;
+ }
const parsedURL = basicURLParse(url, { baseURL: parsedBase });
if (parsedURL === null) {
throw new TypeError(`Invalid URL: ${url}`);
diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/index.ts b/packages/taler-wallet-webextension/src/wallet/AddExchange/index.ts
index d59501212..3d5a105ec 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddExchange/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddExchange/index.ts
@@ -14,12 +14,12 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { OperationFailWithBody, OperationOk, OperationResult, TalerExchangeApi } from "@gnu-taler/taler-util";
+import { OperationFailWithBody, OperationOk, TalerExchangeApi } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
import { TextFieldHandler } from "../../mui/handlers.js";
-import { compose, StateViewMap } from "../../utils/index.js";
+import { StateViewMap, compose } from "../../utils/index.js";
import { useComponentState } from "./state.js";
import { ConfirmView, VerifyView } from "./views.js";
@@ -37,6 +37,7 @@ export type State = State.Loading
export type CheckExchangeErrors = {
"invalid-version": string;
"invalid-currency": string;
+ "not-found": void;
"already-active": void;
"invalid-protocol": void;
}
diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts b/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts
index 5ae0aa8f4..4a04f762a 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts
@@ -14,15 +14,15 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { ExchangeEntryStatus, OperationFailWithBody, OperationOk, TalerExchangeApi, TalerExchangeHttpClient, canonicalizeBaseUrl, opKnownFailureWithBody } from "@gnu-taler/taler-util";
+import { ExchangeEntryStatus, TalerExchangeHttpClient, canonicalizeBaseUrl, opKnownFailureWithBody } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser";
import { useCallback, useEffect, useState } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { withSafe } from "../../mui/handlers.js";
import { RecursiveState } from "../../utils/index.js";
import { CheckExchangeErrors, Props, State } from "./index.js";
-import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser";
function urlFromInput(str: string): URL {
let result: URL;
@@ -83,6 +83,9 @@ export function useComponentState({ onBack, currency, noDebounce }: Props): Recu
*/
const api = new TalerExchangeHttpClient(baseUrl.href, new BrowserFetchHttpLib() as any);
const config = await api.getConfig()
+ if (config.type === "fail") {
+ return opKnownFailureWithBody<CheckExchangeErrors>("not-found", undefined)
+ }
if (!api.isCompatible(config.body.version)) {
return opKnownFailureWithBody<CheckExchangeErrors>("invalid-version", config.body.version)
}
@@ -155,7 +158,7 @@ function useDebounce<T>(
const [result, setResult] = useState<T | undefined>(undefined);
const [error, setError] = useState<Error | undefined>(undefined);
- const [handler, setHandler] = useState<any | undefined>(undefined);
+ const [handler, setHandler] = useState<number | undefined>(undefined);
if (!disabled) {
useEffect(() => {
@@ -180,7 +183,7 @@ function useDebounce<T>(
setResult(undefined);
}
}, 500);
- setHandler(h);
+ setHandler(h as unknown as number);
}, [value, setHandler, onTrigger]);
}
diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/views.tsx b/packages/taler-wallet-webextension/src/wallet/AddExchange/views.tsx
index 489d7eb3b..21309fd7b 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddExchange/views.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/AddExchange/views.tsx
@@ -17,13 +17,18 @@
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { ErrorMessage } from "../../components/ErrorMessage.js";
-import { Input, LightText, SubTitle, Title, WarningBox } from "../../components/styled/index.js";
+import {
+ Input,
+ LightText,
+ SubTitle,
+ Title,
+ WarningBox,
+} from "../../components/styled/index.js";
import { TermsOfService } from "../../components/TermsOfService/index.js";
import { Button } from "../../mui/Button.js";
import { State } from "./index.js";
import { assertUnreachable } from "@gnu-taler/taler-util";
-
export function VerifyView({
expectedCurrency,
onCancel,
@@ -57,40 +62,71 @@ export function VerifyView({
{(() => {
if (!result) return;
if (result.type == "ok") {
- return <LightText>
- <i18n.Translate>
- An exchange has been found! Review the information and click next
- </i18n.Translate>
- </LightText>
+ return (
+ <LightText>
+ <i18n.Translate>
+ An exchange has been found! Review the information and click
+ next
+ </i18n.Translate>
+ </LightText>
+ );
}
switch (result.case) {
case "already-active": {
- return <WarningBox>
- <i18n.Translate>This exchange is already in your list.</i18n.Translate>
- </WarningBox>
+ return (
+ <WarningBox>
+ <i18n.Translate>
+ This exchange is already in your list.
+ </i18n.Translate>
+ </WarningBox>
+ );
}
case "invalid-protocol": {
- return <WarningBox>
- <i18n.Translate>Only exchange accessible through "http" and "https" are allowed.</i18n.Translate>
- </WarningBox>
+ return (
+ <WarningBox>
+ <i18n.Translate>
+ Only exchange accessible through "http" and "https" are
+ allowed.
+ </i18n.Translate>
+ </WarningBox>
+ );
}
case "invalid-version": {
- return <WarningBox>
- <i18n.Translate>This exchange protocol version is not supported: "{result.body}".</i18n.Translate>
- </WarningBox>
+ return (
+ <WarningBox>
+ <i18n.Translate>
+ This exchange protocol version is not supported: "
+ {result.body}".
+ </i18n.Translate>
+ </WarningBox>
+ );
}
case "invalid-currency": {
- return <WarningBox>
- <i18n.Translate>This exchange currency "{result.body}" doesn&apos;t match the expected currency {expectedCurrency}.</i18n.Translate>
- </WarningBox>
+ return (
+ <WarningBox>
+ <i18n.Translate>
+ This exchange currency "{result.body}" doesn&apos;t match
+ the expected currency {expectedCurrency}.
+ </i18n.Translate>
+ </WarningBox>
+ );
+ }
+ case "not-found": {
+ return (
+ <WarningBox>
+ <i18n.Translate>
+ No exchange found in that URL.
+ </i18n.Translate>
+ </WarningBox>
+ );
}
default: {
- assertUnreachable(result.case)
+ assertUnreachable(result.case);
}
}
})()}
<p>
- <Input invalid={result && result.type !== "ok"} >
+ <Input invalid={result && result.type !== "ok"}>
<label>URL</label>
<input
type="text"
@@ -98,7 +134,7 @@ export function VerifyView({
value={url.value}
onInput={(e) => {
if (url.onInput) {
- url.onInput(e.currentTarget.value)
+ url.onInput(e.currentTarget.value);
}
}}
/>
@@ -138,10 +174,7 @@ export function VerifyView({
</Button>
<Button
variant="contained"
- disabled={
- !result ||
- result.type !== "ok"
- }
+ disabled={!result || result.type !== "ok"}
onClick={onAccept}
>
<i18n.Translate>Next</i18n.Translate>
@@ -149,14 +182,22 @@ export function VerifyView({
</footer>
<section>
<ul>
- {knownExchanges.map(ex => {
- return <li><a href="#" onClick={(e) => {
- if (url.onInput) {
- url.onInput(ex.href)
- }
- e.preventDefault()
- }}>
- {ex.href}</a></li>
+ {knownExchanges.map((ex) => {
+ return (
+ <li key={ex.href}>
+ <a
+ href="#"
+ onClick={(e) => {
+ if (url.onInput) {
+ url.onInput(ex.href);
+ }
+ e.preventDefault();
+ }}
+ >
+ {ex.href}
+ </a>
+ </li>
+ );
})}
</ul>
</section>
@@ -164,7 +205,6 @@ export function VerifyView({
);
}
-
export function ConfirmView({
url,
onCancel,
@@ -186,8 +226,7 @@ export function ConfirmView({
</div>
</section>
-
- <TermsOfService key="terms" exchangeUrl={url} >
+ <TermsOfService key="terms" exchangeUrl={url}>
<footer>
<Button
key="cancel"
diff --git a/packages/web-util/src/context/activity.ts b/packages/web-util/src/context/activity.ts
index c38f133a1..9a16f6673 100644
--- a/packages/web-util/src/context/activity.ts
+++ b/packages/web-util/src/context/activity.ts
@@ -55,10 +55,9 @@ export interface APIClient<T, C> {
}
export interface MerchantLib {
- management: TalerMerchantManagementHttpClient;
+ instance: TalerMerchantManagementHttpClient;
authenticate: TalerAuthenticationHttpClient;
- instance: (instanceId: string) => TalerMerchantInstanceHttpClient;
- impersonate: (instanceId: string) => TalerAuthenticationHttpClient;
+ subInstanceApi: (instanceId: string) => MerchantLib;
}
export interface BankLib {
diff --git a/packages/web-util/src/context/bank-api.ts b/packages/web-util/src/context/bank-api.ts
index a5e5654ac..d2938f150 100644
--- a/packages/web-util/src/context/bank-api.ts
+++ b/packages/web-util/src/context/bank-api.ts
@@ -25,7 +25,7 @@ import {
TalerCoreBankCacheEviction,
TalerCoreBankHttpClient,
TalerCorebankApi,
- TalerError
+ TalerError,
} from "@gnu-taler/taler-util";
import {
ComponentChildren,
@@ -56,7 +56,8 @@ export type BankContextType = {
// @ts-expect-error default value to undefined, should it be another thing?
const BankContext = createContext<BankContextType>(undefined);
-export const useBankCoreApiContext = (): BankContextType => useContext(BankContext);
+export const useBankCoreApiContext = (): BankContextType =>
+ useContext(BankContext);
enum VersionHint {
NONE,
@@ -65,7 +66,7 @@ enum VersionHint {
type Evictors = {
conversion?: CacheEvictor<TalerBankConversionCacheEviction>;
bank?: CacheEvictor<TalerCoreBankCacheEviction>;
-}
+};
type ConfigResult<T> =
| undefined
@@ -81,13 +82,15 @@ export const BankApiProvider = ({
}: {
baseUrl: URL;
children: ComponentChildren;
- evictors?: Evictors,
+ evictors?: Evictors;
frameOnError: FunctionComponent<{ children: ComponentChildren }>;
}): VNode => {
- const [checked, setChecked] = useState<ConfigResult<TalerCorebankApi.Config>>();
+ const [checked, setChecked] =
+ useState<ConfigResult<TalerCorebankApi.Config>>();
const { i18n } = useTranslationContext();
- const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } = buildBankApiClient(baseUrl, evictors);
+ const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =
+ buildBankApiClient(baseUrl, evictors);
useEffect(() => {
getRemoteConfig()
@@ -110,7 +113,9 @@ export const BankApiProvider = ({
}, []);
if (checked === undefined) {
- return h(frameOnError, { children: h("div", {}, "checking compatibility with server...") });
+ return h(frameOnError, {
+ children: h("div", {}, "checking compatibility with server..."),
+ });
}
if (checked.type === "error") {
return h(frameOnError, {
@@ -141,7 +146,9 @@ export const BankApiProvider = ({
});
};
-function buildBankApiClient(url: URL, evictors: Evictors,
+function buildBankApiClient(
+ url: URL,
+ evictors: Evictors,
): APIClient<BankLib, TalerCorebankApi.Config> {
const httpFetch = new BrowserFetchHttpLib({
enableThrottling: true,
@@ -154,11 +161,7 @@ function buildBankApiClient(url: URL, evictors: Evictors,
},
});
- const bank = new TalerCoreBankHttpClient(
- url.href,
- httpLib,
- evictors.bank,
- );
+ const bank = new TalerCoreBankHttpClient(url.href, httpLib, evictors.bank);
const conversion = new TalerBankConversionHttpClient(
bank.getConversionInfoAPI().href,
httpLib,
@@ -170,32 +173,36 @@ function buildBankApiClient(url: URL, evictors: Evictors,
httpLib,
);
- async function getRemoteConfig() {
- const resp = await bank.getConfig()
- return resp.body
+ async function getRemoteConfig(): Promise<TalerCorebankApi.Config> {
+ const resp = await bank.getConfig();
+ if (resp.type === "fail") {
+ throw TalerError.fromUncheckedDetail(resp.detail);
+ }
+ return resp.body;
}
return {
getRemoteConfig,
VERSION: bank.PROTOCOL_VERSION,
lib: {
- bank, conversion, auth
+ bank,
+ conversion,
+ auth,
},
onActivity: tracker.subscribe,
cancelRequest: httpLib.cancelRequest,
};
}
-
export const BankApiProviderTesting = ({
children,
value,
}: {
- value: BankContextType
+ value: BankContextType;
children: ComponentChildren;
}): VNode => {
return h(BankContext.Provider, {
value,
children,
});
-}
+};
diff --git a/packages/web-util/src/context/merchant-api.ts b/packages/web-util/src/context/merchant-api.ts
index 9e2869b62..26d9c9e85 100644
--- a/packages/web-util/src/context/merchant-api.ts
+++ b/packages/web-util/src/context/merchant-api.ts
@@ -23,7 +23,6 @@ import {
TalerError,
TalerMerchantApi,
TalerMerchantInstanceCacheEviction,
- TalerMerchantInstanceHttpClient,
TalerMerchantManagementCacheEviction,
TalerMerchantManagementHttpClient,
} from "@gnu-taler/taler-util";
@@ -35,14 +34,13 @@ import {
h,
} from "preact";
import { useContext, useEffect, useState } from "preact/hooks";
+import { BrowserFetchHttpLib } from "../index.browser.js";
import {
APIClient,
ActiviyTracker,
MerchantLib,
Subscriber,
} from "./activity.js";
-import { useTranslationContext } from "./translation.js";
-import { BrowserFetchHttpLib, ErrorLoading } from "../index.browser.js";
/**
*
@@ -56,6 +54,7 @@ export type MerchantContextType = {
hints: VersionHint[];
onActivity: Subscriber<ObservabilityEvent>;
cancelRequest: (eventId: string) => void;
+ changeBackend: (url: URL) => void;
};
// FIXME: below
@@ -94,14 +93,17 @@ export const MerchantApiProvider = ({
baseUrl: URL;
evictors?: Evictors;
children: ComponentChildren;
- frameOnError: FunctionComponent<{ state: ConfigResultFail<TalerMerchantApi.VersionResponse> | undefined }>;
+ frameOnError: FunctionComponent<{
+ state: ConfigResultFail<TalerMerchantApi.VersionResponse> | undefined;
+ }>;
}): VNode => {
const [checked, setChecked] =
useState<ConfigResult<TalerMerchantApi.VersionResponse>>();
- const { i18n } = useTranslationContext();
+
+ const [merchantEndpoint, changeMerchantEndpoint] = useState(baseUrl);
const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =
- buildMerchantApiClient(baseUrl, evictors);
+ buildMerchantApiClient(merchantEndpoint, evictors);
useEffect(() => {
getRemoteConfig()
@@ -128,11 +130,12 @@ export const MerchantApiProvider = ({
}
const value: MerchantContextType = {
- url: baseUrl,
+ url: merchantEndpoint,
config: checked.config,
onActivity: onActivity,
lib,
cancelRequest,
+ changeBackend: changeMerchantEndpoint,
hints: checked.hints,
};
return h(MerchantContext.Provider, {
@@ -157,40 +160,51 @@ function buildMerchantApiClient(
},
});
- const management = new TalerMerchantManagementHttpClient(
+ const instance = new TalerMerchantManagementHttpClient(
url.href,
httpLib,
evictors.management,
);
- const instance = (instanceId: string) =>
- new TalerMerchantInstanceHttpClient(
- management.getSubInstanceAPI(instanceId).href,
- httpLib,
- evictors.instance ? evictors.instance(instanceId) : undefined,
- );
const authenticate = new TalerAuthenticationHttpClient(
- management.getAuthenticationAPI().href,
+ instance.getAuthenticationAPI().href,
httpLib,
);
- const impersonate = (instanceId: string) =>
- new TalerAuthenticationHttpClient(
- instance(instanceId).getAuthenticationAPI().href,
- httpLib,
- );
+
+ // const instance = (instanceId: string): TalerMerchantInstanceHttpClient => {
+ // return new TalerMerchantInstanceHttpClient(
+ // management.getSubInstanceAPI(instanceId).href,
+ // httpLib,
+ // evictors.instance ? evictors.instance(instanceId) : undefined,
+ // );
+ // }
+ // const impersonate = (instanceId: string): TalerAuthenticationHttpClient => {
+ // return new TalerAuthenticationHttpClient(
+ // instance(instanceId).getAuthenticationAPI().href,
+ // httpLib,
+ // );
+ // }
+ const rootUrl = url;
+ function getSubInstanceAPI(instanceId: string): MerchantLib {
+ const newURL = new URL(`instance/${instanceId}/`, rootUrl);
+ const api = buildMerchantApiClient(newURL, evictors);
+ return api.lib;
+ }
async function getRemoteConfig(): Promise<TalerMerchantApi.VersionResponse> {
- const resp = await management.getConfig();
+ const resp = await instance.getConfig();
+ if (resp.type === "fail") {
+ throw TalerError.fromUncheckedDetail(resp.detail)
+ }
return resp.body;
}
return {
getRemoteConfig,
- VERSION: management.PROTOCOL_VERSION,
+ VERSION: instance.PROTOCOL_VERSION,
lib: {
- management,
- authenticate,
- impersonate,
instance,
+ authenticate,
+ subInstanceApi: getSubInstanceAPI,
},
onActivity: tracker.subscribe,
cancelRequest: httpLib.cancelRequest,
diff --git a/packages/web-util/src/utils/http-impl.sw.ts b/packages/web-util/src/utils/http-impl.sw.ts
index 4d7f3a8a1..3c4b8b587 100644
--- a/packages/web-util/src/utils/http-impl.sw.ts
+++ b/packages/web-util/src/utils/http-impl.sw.ts
@@ -18,11 +18,10 @@
* Imports.
*/
import {
+ Duration,
RequestThrottler,
- TalerErrorCode,
TalerError,
- Duration,
- CancellationToken,
+ TalerErrorCode
} from "@gnu-taler/taler-util";
import {