gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wip #8655


From: gnunet
Subject: [taler-wallet-core] branch master updated: wip #8655
Date: Wed, 27 Mar 2024 05:05:18 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 237c4e8ad wip #8655
237c4e8ad is described below

commit 237c4e8adae997e84f5fb7a8fe5c03b1148e99dc
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed Mar 27 01:05:10 2024 -0300

    wip #8655
---
 .../merchant-backoffice-ui/src/Application.tsx     |   39 +-
 .../src/components/form/InputStock.tsx             |    9 +-
 .../merchant-backoffice-ui/src/context/instance.ts |   35 -
 .../merchant-backoffice-ui/src/context/session.ts  |    7 +-
 .../merchant-backoffice-ui/src/declaration.d.ts    | 1647 --------------------
 .../merchant-backoffice-ui/src/hooks/backend.ts    |   10 -
 .../src/hooks/instance.test.ts                     |   37 +-
 .../merchant-backoffice-ui/src/hooks/instance.ts   |  211 +--
 .../merchant-backoffice-ui/src/hooks/templates.ts  |   22 +-
 .../src/paths/admin/create/CreatePage.tsx          |    2 +-
 .../src/paths/admin/create/index.tsx               |    8 +-
 .../src/paths/admin/list/index.tsx                 |   21 +-
 .../src/paths/instance/details/index.tsx           |   12 +-
 .../src/paths/instance/templates/list/index.tsx    |    2 +-
 .../src/paths/instance/token/DetailPage.tsx        |    7 +-
 .../src/paths/instance/token/index.tsx             |   12 +-
 .../src/paths/instance/update/index.tsx            |   30 +-
 packages/taler-util/src/http-client/merchant.ts    |    4 +-
 packages/taler-util/src/http-client/types.ts       |    4 +-
 packages/web-util/src/context/merchant-api.ts      |   25 +-
 packages/web-util/src/utils/request.ts             |    2 +-
 21 files changed, 146 insertions(+), 2000 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/Application.tsx 
b/packages/merchant-backoffice-ui/src/Application.tsx
index d752d612d..497f49c0e 100644
--- a/packages/merchant-backoffice-ui/src/Application.tsx
+++ b/packages/merchant-backoffice-ui/src/Application.tsx
@@ -19,12 +19,14 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { canonicalizeBaseUrl } from "@gnu-taler/taler-util";
+import { TalerMerchantApi, assertUnreachable, canonicalizeBaseUrl } from 
"@gnu-taler/taler-util";
 import {
   BrowserHashNavigationProvider,
+  ConfigResultFail,
   MerchantApiProvider,
   TalerWalletIntegrationBrowserProvider,
-  TranslationProvider
+  TranslationProvider,
+  useTranslationContext
 } from "@gnu-taler/web-util/browser";
 import { VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
@@ -34,8 +36,10 @@ import { Loading } from "./components/exception/loading.js";
 import { SettingsProvider } from "./context/settings.js";
 import { strings } from "./i18n/strings.js";
 import { MerchantUiSettings, buildDefaultBackendBaseURL, fetchSettings } from 
"./settings.js";
+import { NotificationCard } from "./components/menu/index.js";
 const WITH_LOCAL_STORAGE_CACHE = false;
 
+
 export function Application(): VNode {
   const [settings, setSettings] = useState<MerchantUiSettings>();
   useEffect(() => {
@@ -53,7 +57,7 @@ export function Application(): VNode {
           de: strings["de"].completeness,
         }}
       >
-        <MerchantApiProvider baseUrl={new URL("/", baseUrl)} frameOnError={({ 
children }) => <div>{children}</div>}>
+        <MerchantApiProvider baseUrl={new URL("/", baseUrl)} 
frameOnError={OnConfigError}>
           <SWRConfig
             value={{
               provider: WITH_LOCAL_STORAGE_CACHE
@@ -136,3 +140,32 @@ function localStorageProvider(): Map<unknown, unknown> {
   });
   return map;
 }
+
+function OnConfigError({ state }: { state: 
ConfigResultFail<TalerMerchantApi.VersionResponse> | undefined }): VNode {
+  const { i18n } = useTranslationContext();
+  if (!state) {
+    return <i18n.Translate>checking compatibility with 
server...</i18n.Translate>
+  }
+  switch (state.type) {
+    case "error": {
+      return <NotificationCard
+        notification={{
+          message: i18n.str`Contacting the server failed`,
+          description: state.error.message,
+          details: JSON.stringify(state.error.errorDetail, undefined, 2),
+          type: "ERROR",
+        }}
+      />
+    }
+    case "incompatible": {
+      return <NotificationCard
+        notification={{
+          message: i18n.str`The server version is not supported`,
+          description: i18n.str`Supported version "${state.supported}", server 
version "${state.result.version}".`,
+          type: "WARN",
+        }}
+      />
+    }
+    default: assertUnreachable(state)
+  }
+}
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx 
b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
index e47259732..8104d1f9f 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx
@@ -18,7 +18,8 @@
  *
  * @author Sebastian Javier Marchano (sebasjm)
  */
-import { Location, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { TalerMerchantApi, TalerProtocolTimestamp } from 
"@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
 import { Fragment, h } from "preact";
 import { useLayoutEffect, useState } from "preact/hooks";
 import { FormErrors, FormProvider } from "./FormProvider.js";
@@ -27,7 +28,6 @@ import { InputGroup } from "./InputGroup.js";
 import { InputLocation } from "./InputLocation.js";
 import { InputNumber } from "./InputNumber.js";
 import { InputProps, useField } from "./useField.js";
-import { TalerMerchantApi } from "@gnu-taler/taler-util";
 
 export interface Props<T> extends InputProps<T> {
   alreadyExist?: boolean;
@@ -40,7 +40,7 @@ export interface Stock {
   lost: number;
   sold: number;
   address?: TalerMerchantApi.Location;
-  nextRestock?: Timestamp;
+  nextRestock?: TalerProtocolTimestamp;
 }
 
 interface StockDelta {
@@ -133,8 +133,7 @@ export function InputStock<T>({
   const stockAddedErrors: FormErrors<typeof addedStock> = {
     lost:
       currentStock + addedStock.incoming < addedStock.lost
-        ? i18n.str`lost cannot be greater than current and incoming (max ${
-            currentStock + addedStock.incoming
+        ? i18n.str`lost cannot be greater than current and incoming (max 
${currentStock + addedStock.incoming
           })`
         : undefined,
   };
diff --git a/packages/merchant-backoffice-ui/src/context/instance.ts 
b/packages/merchant-backoffice-ui/src/context/instance.ts
deleted file mode 100644
index 9b67f7170..000000000
--- a/packages/merchant-backoffice-ui/src/context/instance.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createContext } from "preact";
-import { useContext } from "preact/hooks";
-
-interface Type {
-  id: string;
-  token?: LoginToken;
-  admin?: boolean;
-  changeToken: (t?: LoginToken) => void;
-}
-
-const Context = createContext<Type>({} as any);
-
-const InstanceContextProvider = Context.Provider;
-const useInstanceContext = (): Type => useContext(Context);
diff --git a/packages/merchant-backoffice-ui/src/context/session.ts 
b/packages/merchant-backoffice-ui/src/context/session.ts
index 83f3f113a..9d63d8e33 100644
--- a/packages/merchant-backoffice-ui/src/context/session.ts
+++ b/packages/merchant-backoffice-ui/src/context/session.ts
@@ -215,7 +215,8 @@ export function useSessionContext(): SessionStateHandler {
           .href,
         isAdmin: info.instance === DEFAULT_ADMIN_USERNAME,
         instance: info.instance,
-        token: info.token,
+        // FIXME: bank and merchant should have consistent behavior
+        token: info.token?.substring("secret-token:".length) as AccessToken,
         impersonate: {
           originalBackendUrl: state.backendUrl,
           originalToken: state.token,
@@ -239,7 +240,9 @@ export function useSessionContext(): SessionStateHandler {
         impersonate: undefined,
         ...state,
         status: "loggedIn",
-        token: info.token,
+        // FIXME: bank and merchant should have consistent behavior
+        token: info.token?.substring("secret-token:".length) as AccessToken,
+        // token: info.token,
       };
       update(nextState);
       cleanAllCache();
diff --git a/packages/merchant-backoffice-ui/src/declaration.d.ts 
b/packages/merchant-backoffice-ui/src/declaration.d.ts
index 93fecd9c4..1baf80ba6 100644
--- a/packages/merchant-backoffice-ui/src/declaration.d.ts
+++ b/packages/merchant-backoffice-ui/src/declaration.d.ts
@@ -19,1653 +19,6 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-type HashCode = string;
-type EddsaPublicKey = string;
-type EddsaSignature = string;
-type WireTransferIdentifierRawP = string;
-type RelativeTime = TalerProtocolDuration;
-type ImageDataUrl = string;
-type MerchantUserType = "business" | "individual";
-
-
-interface WithId {
-  id: string;
-}
-
-interface Timestamp {
-  // Milliseconds since epoch, or the special
-  // value "forever" to represent an event that will
-  // never happen.
-  t_s: number | "never";
-}
-interface TalerProtocolDuration {
-  d_us: number | "forever";
-}
-interface Duration {
-  d_ms: number | "forever";
-}
-
 interface WithId {
   id: string;
 }
-
-type Amount = string;
-type UUID = string;
-type Integer = number;
-
-interface WireAccount {
-  // payto:// URI identifying the account and wire method
-  payto_uri: string;
-
-  // URI to convert amounts from or to the currency used by
-  // this wire account of the exchange. Missing if no
-  // conversion is applicable.
-  conversion_url?: string;
-
-  // Restrictions that apply to bank accounts that would send
-  // funds to the exchange (crediting this exchange bank account).
-  // Optional, empty array for unrestricted.
-  credit_restrictions: AccountRestriction[];
-
-  // Restrictions that apply to bank accounts that would receive
-  // funds from the exchange (debiting this exchange bank account).
-  // Optional, empty array for unrestricted.
-  debit_restrictions: AccountRestriction[];
-
-  // Signature using the exchange's offline key over
-  // a TALER_MasterWireDetailsPS
-  // with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS.
-  master_sig: EddsaSignature;
-}
-
-type AccountRestriction = RegexAccountRestriction | DenyAllAccountRestriction;
-
-// Account restriction that disables this type of
-// account for the indicated operation categorically.
-interface DenyAllAccountRestriction {
-  type: "deny";
-}
-
-// Accounts interacting with this type of account
-// restriction must have a payto://-URI matching
-// the given regex.
-interface RegexAccountRestriction {
-  type: "regex";
-
-  // Regular expression that the payto://-URI of the
-  // partner account must follow.  The regular expression
-  // should follow posix-egrep, but without support for character
-  // classes, GNU extensions, back-references or intervals. See
-  // 
https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
-  // for a description of the posix-egrep syntax. Applications
-  // may support regexes with additional features, but exchanges
-  // must not use such regexes.
-  payto_regex: string;
-
-  // Hint for a human to understand the restriction
-  // (that is hopefully easier to comprehend than the regex itself).
-  human_hint: string;
-
-  // Map from IETF BCP 47 language tags to localized
-  // human hints.
-  human_hint_i18n?: { [lang_tag: string]: string };
-}
-interface LoginToken {
-  token: string,
-  expiration: Timestamp,
-}
-// token used to get loginToken
-// must forget after used
-declare const __ac_token: unique symbol;
-
-namespace dead_ExchangeBackend2 {
-  interface WireResponse {
-    // Master public key of the exchange, must match the key returned in /keys.
-    master_public_key: EddsaPublicKey;
-
-    // Array of wire accounts operated by the exchange for
-    // incoming wire transfers.
-    accounts: WireAccount[];
-
-    // Object mapping names of wire methods (i.e. "sepa" or "x-taler-bank")
-    // to wire fees.
-    fees: { method: AggregateTransferFee };
-  }
-  interface AggregateTransferFee {
-    // Per transfer wire transfer fee.
-    wire_fee: Amount;
-
-    // Per transfer closing fee.
-    closing_fee: Amount;
-
-    // What date (inclusive) does this fee go into effect?
-    // The different fees must cover the full time period in which
-    // any of the denomination keys are valid without overlap.
-    start_date: Timestamp;
-
-    // What date (exclusive) does this fee stop going into effect?
-    // The different fees must cover the full time period in which
-    // any of the denomination keys are valid without overlap.
-    end_date: Timestamp;
-
-    // Signature of TALER_MasterWireFeePS with
-    // purpose TALER_SIGNATURE_MASTER_WIRE_FEES.
-    sig: EddsaSignature;
-  }
-}
-namespace dead_MerchantBackend2 {
-  interface ErrorDetail {
-    // Numeric error code unique to the condition.
-    // The other arguments are specific to the error value reported here.
-    code: number;
-
-    // Human-readable description of the error, i.e. "missing parameter", 
"commitment violation", ...
-    // Should give a human-readable hint about the error's nature. Optional, 
may change without notice!
-    hint?: string;
-
-    // Optional detail about the specific input value that failed. May change 
without notice!
-    detail?: string;
-
-    // Name of the parameter that was bogus (if applicable).
-    parameter?: string;
-
-    // Path to the argument that was bogus (if applicable).
-    path?: string;
-
-    // Offset of the argument that was bogus (if applicable).
-    offset?: string;
-
-    // Index of the argument that was bogus (if applicable).
-    index?: string;
-
-    // Name of the object that was bogus (if applicable).
-    object?: string;
-
-    // Name of the currency than was problematic (if applicable).
-    currency?: string;
-
-    // Expected type (if applicable).
-    type_expected?: string;
-
-    // Type that was provided instead (if applicable).
-    type_actual?: string;
-  }
-
-  // Delivery location, loosely modeled as a subset of
-  // ISO20022's PostalAddress25.
-  interface Tax {
-    // the name of the tax
-    name: string;
-
-    // amount paid in tax
-    tax: Amount;
-  }
-
-  interface Auditor {
-    // official name
-    name: string;
-
-    // Auditor's public key
-    auditor_pub: EddsaPublicKey;
-
-    // Base URL of the auditor
-    url: string;
-  }
-  interface Exchange {
-    // the exchange's base URL
-    url: string;
-
-    // master public key of the exchange
-    master_pub: EddsaPublicKey;
-  }
-
-  interface Product {
-    // merchant-internal identifier for the product.
-    product_id?: string;
-
-    // Human-readable product description.
-    description: string;
-
-    // Map from IETF BCP 47 language tags to localized descriptions
-    description_i18n?: { [lang_tag: string]: string };
-
-    // The number of units of the product to deliver to the customer.
-    quantity: Integer;
-
-    // The unit in which the product is measured (liters, kilograms, packages, 
etc.)
-    unit: string;
-
-    // The price of the product; this is the total price for quantity times 
unit of this product.
-    price?: Amount;
-
-    // An optional base64-encoded product image
-    image: ImageDataUrl;
-
-    // a list of taxes paid by the merchant for this product. Can be empty.
-    taxes: Tax[];
-
-    // time indicating when this product should be delivered
-    delivery_date?: TalerProtocolTimestamp;
-
-    // Minimum age buyer must have (in years). Default is 0.
-    minimum_age?: Integer;
-  }
-  interface Merchant {
-    // label for a location with the business address of the merchant
-    address: Location;
-
-    // the merchant's legal name of business
-    name: string;
-
-    // label for a location that denotes the jurisdiction for disputes.
-    // Some of the typical fields for a location (such as a street address) 
may be absent.
-    jurisdiction: Location;
-  }
-
-  interface VersionResponse {
-    // libtool-style representation of the Merchant protocol version, see
-    // 
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
-    // The format is "current:revision:age".
-    version: string;
-
-    // Name of the protocol.
-    name: "taler-merchant";
-
-    // Default (!) currency supported by this backend.
-    // This is the currency that the backend should
-    // suggest by default to the user when entering
-    // amounts. See currencies for a list of
-    // supported currencies and how to render them.
-    currency: string;
-
-    // How services should render currencies supported
-    // by this backend.  Maps
-    // currency codes (e.g. "EUR" or "KUDOS") to
-    // the respective currency specification.
-    // All currencies in this map are supported by
-    // the backend.  Note that the actual currency
-    // specifications are a *hint* for applications
-    // that would like *advice* on how to render amounts.
-    // Applications *may* ignore the currency specification
-    // if they know how to render currencies that they are
-    // used with.
-    currencies: { currency: CurrencySpecification };
-
-    // Array of exchanges trusted by the merchant.
-    // Since protocol v6.
-    exchanges: ExchangeConfigInfo[];
-  }
-
-  interface ExchangeConfigInfo {
-
-    // Base URL of the exchange REST API.
-    base_url: string;
-
-    // Currency for which the merchant is configured
-    // to trust the exchange.
-    // May not be the one the exchange actually uses,
-    // but is the only one we would trust this exchange for.
-    currency: string;
-
-    // Offline master public key of the exchange. The
-    // /keys data must be signed with this public
-    // key for us to trust it.
-    master_pub: EddsaPublicKey;
-  }
-  interface Location {
-    // Nation with its own government.
-    country?: string;
-
-    // Identifies a subdivision of a country such as state, region, county.
-    country_subdivision?: string;
-
-    // Identifies a subdivision within a country sub-division.
-    district?: string;
-
-    // Name of a built-up area, with defined boundaries, and a local 
government.
-    town?: string;
-
-    // Specific location name within the town.
-    town_location?: string;
-
-    // Identifier consisting of a group of letters and/or numbers that
-    // is added to a postal address to assist the sorting of mail.
-    post_code?: string;
-
-    // Name of a street or thoroughfare.
-    street?: string;
-
-    // Name of the building or house.
-    building_name?: string;
-
-    // Number that identifies the position of a building on a street.
-    building_number?: string;
-
-    // Free-form address lines, should not exceed 7 elements.
-    address_lines?: string[];
-  }
-  namespace dead_Instances2 {
-    //POST /private/instances/$INSTANCE/auth
-    interface InstanceAuthConfigurationMessage {
-      // Type of authentication.
-      // "external":  The mechant backend does not do
-      //   any authentication checks.  Instead an API
-      //   gateway must do the authentication.
-      // "token": The merchant checks an auth token.
-      //   See "token" for details.
-      method: "external" | "token";
-
-      // For method "external", this field is mandatory.
-      // The token MUST begin with the string "secret-token:".
-      // After the auth token has been set (with method "token"),
-      // the value must be provided in a "Authorization: Bearer $token"
-      // header.
-      token?: string;
-    }
-    //POST /private/instances
-    interface InstanceConfigurationMessage {
-      // Name of the merchant instance to create (will become $INSTANCE).
-      id: string;
-
-      // Merchant name corresponding to this instance.
-      name: string;
-
-      // Type of the user (business or individual).
-      // Defaults to 'business'. Should become mandatory field
-      // in the future, left as optional for API compatibility for now.
-      user_type?: MerchantUserType;
-
-      // Merchant email for customer contact.
-      email?: string;
-
-      // Merchant public website.
-      website?: string;
-
-      // Merchant logo.
-      logo?: ImageDataUrl;
-
-      // "Authentication" header required to authorize management access the 
instance.
-      // Optional, if not given authentication will be disabled for
-      // this instance (hopefully authentication checks are still
-      // done by some reverse proxy).
-      auth: InstanceAuthConfigurationMessage;
-
-      // The merchant's physical address (to be put into contracts).
-      address: Location;
-
-      // The jurisdiction under which the merchant conducts its business
-      // (to be put into contracts).
-      jurisdiction: Location;
-
-      // Use STEFAN curves to determine default fees?
-      // If false, no fees are allowed by default.
-      // Can always be overridden by the frontend on a per-order basis.
-      use_stefan: boolean;
-
-      //  If the frontend does NOT specify an execution date, how long should
-      // we tell the exchange to wait to aggregate transactions before
-      // executing the wire transfer?  This delay is added to the current
-      // time when we generate the advisory execution time for the exchange.
-      default_wire_transfer_delay: RelativeTime;
-
-      // If the frontend does NOT specify a payment deadline, how long should
-      // offers we make be valid by default?
-      default_pay_delay: RelativeTime;
-    }
-
-    // PATCH /private/instances/$INSTANCE
-    interface InstanceReconfigurationMessage {
-
-      // Merchant name corresponding to this instance.
-      name: string;
-
-      // Type of the user (business or individual).
-      // Defaults to 'business'. Should become mandatory field
-      // in the future, left as optional for API compatibility for now.
-      user_type?: MerchantUserType;
-
-      // Merchant email for customer contact.
-      email?: string;
-
-      // Merchant public website.
-      website?: string;
-
-      // Merchant logo.
-      logo?: ImageDataUrl;
-
-      // The merchant's physical address (to be put into contracts).
-      address: Location;
-
-      // The jurisdiction under which the merchant conducts its business
-      // (to be put into contracts).
-      jurisdiction: Location;
-
-      // Use STEFAN curves to determine default fees?
-      // If false, no fees are allowed by default.
-      // Can always be overridden by the frontend on a per-order basis.
-      use_stefan: boolean;
-
-      //  If the frontend does NOT specify an execution date, how long should
-      // we tell the exchange to wait to aggregate transactions before
-      // executing the wire transfer?  This delay is added to the current
-      // time when we generate the advisory execution time for the exchange.
-      default_wire_transfer_delay: RelativeTime;
-
-      // If the frontend does NOT specify a payment deadline, how long should
-      // offers we make be valid by default?
-      default_pay_delay: RelativeTime;
-    }
-
-    //   GET /private/instances
-    interface InstancesResponse {
-      // List of instances that are present in the backend (see Instance)
-      instances: Instance[];
-    }
-
-    interface Instance {
-      // Merchant name corresponding to this instance.
-      name: string;
-
-      // Type of the user ("business" or "individual").
-      user_type: MerchantUserType;
-
-      // Merchant public website.
-      website?: string;
-
-      // Merchant logo.
-      logo?: ImageDataUrl;
-
-      // Merchant instance this response is about ($INSTANCE)
-      id: string;
-
-      // Public key of the merchant/instance, in Crockford Base32 encoding.
-      merchant_pub: EddsaPublicKey;
-
-      // List of the payment targets supported by this instance. Clients can
-      // specify the desired payment target in /order requests.  Note that
-      // front-ends do not have to support wallets selecting payment targets.
-      payment_targets: string[];
-
-      // Has this instance been deleted (but not purged)?
-      deleted: boolean;
-    }
-
-    //GET /private/instances/$INSTANCE
-    interface QueryInstancesResponse {
-
-      // Merchant name corresponding to this instance.
-      name: string;
-      // Type of the user ("business" or "individual").
-      user_type: MerchantUserType;
-
-      // Merchant email for customer contact.
-      email?: string;
-
-      // Merchant public website.
-      website?: string;
-
-      // Merchant logo.
-      logo?: ImageDataUrl;
-
-      // Public key of the merchant/instance, in Crockford Base32 encoding.
-      merchant_pub: EddsaPublicKey;
-
-      // The merchant's physical address (to be put into contracts).
-      address: Location;
-
-      // The jurisdiction under which the merchant conducts its business
-      // (to be put into contracts).
-      jurisdiction: Location;
-
-      // Use STEFAN curves to determine default fees?
-      // If false, no fees are allowed by default.
-      // Can always be overridden by the frontend on a per-order basis.
-      use_stefan: boolean;
-
-      //  If the frontend does NOT specify an execution date, how long should
-      // we tell the exchange to wait to aggregate transactions before
-      // executing the wire transfer?  This delay is added to the current
-      // time when we generate the advisory execution time for the exchange.
-      default_wire_transfer_delay: RelativeTime;
-
-      // If the frontend does NOT specify a payment deadline, how long should
-      // offers we make be valid by default?
-      default_pay_delay: RelativeTime;
-
-      // Authentication configuration.
-      // Does not contain the token when token auth is configured.
-      auth: {
-        method: "external" | "token";
-      };
-    }
-    //   DELETE /private/instances/$INSTANCE
-    interface LoginTokenRequest {
-      // Scope of the token (which kinds of operations it will allow)
-      scope: "readonly" | "write";
-
-      // Server may impose its own upper bound
-      // on the token validity duration
-      duration?: RelativeTime;
-
-      // Can this token be refreshed?
-      // Defaults to false.
-      refreshable?: boolean;
-    }
-    interface LoginTokenSuccessResponse {
-      // The login token that can be used to access resources
-      // that are in scope for some time. Must be prefixed
-      // with "Bearer " when used in the "Authorization" HTTP header.
-      // Will already begin with the RFC 8959 prefix.
-      token: string;
-
-      // Scope of the token (which kinds of operations it will allow)
-      scope: "readonly" | "write";
-
-      // Server may impose its own upper bound
-      // on the token validity duration
-      expiration: Timestamp;
-
-      // Can this token be refreshed?
-      refreshable: boolean;
-    }
-  }
-
-  namespace dead_KYC {
-    //GET /private/instances/$INSTANCE/kyc
-    interface AccountKycRedirects {
-      // Array of pending KYCs.
-      pending_kycs: MerchantAccountKycRedirect[];
-
-      // Array of exchanges with no reply.
-      timeout_kycs: ExchangeKycTimeout[];
-    }
-    interface MerchantAccountKycRedirect {
-      // URL that the user should open in a browser to
-      // proceed with the KYC process (as returned
-      // by the exchange's /kyc-check/ endpoint).
-      // Optional, missing if the account is blocked
-      // due to AML and not due to KYC.
-      kyc_url?: string;
-
-      // Base URL of the exchange this is about.
-      exchange_url: string;
-
-      // AML status of the account.
-      aml_status: number;
-
-      // Our bank wire account this is about.
-      payto_uri: string;
-    }
-    interface ExchangeKycTimeout {
-      // Base URL of the exchange this is about.
-      exchange_url: string;
-
-      // Numeric error code indicating errors the exchange
-      // returned, or TALER_EC_INVALID for none.
-      exchange_code: number;
-
-      // HTTP status code returned by the exchange when we asked for
-      // information about the KYC status.
-      // 0 if there was no response at all.
-      exchange_http_status: number;
-    }
-
-  }
-
-  namespace dead_BankAccounts {
-
-    interface AccountAddDetails {
-
-      // payto:// URI of the account.
-      payto_uri: string;
-
-      // URL from where the merchant can download information
-      // about incoming wire transfers to this account.
-      credit_facade_url?: string;
-
-      // Credentials to use when accessing the credit facade.
-      // Never returned on a GET (as this may be somewhat
-      // sensitive data). Can be set in POST
-      // or PATCH requests to update (or delete) credentials.
-      // To really delete credentials, set them to the type: "none".
-      credit_facade_credentials?: FacadeCredentials;
-
-    }
-
-    type FacadeCredentials =
-      | NoFacadeCredentials
-      | BasicAuthFacadeCredentials;
-
-    interface NoFacadeCredentials {
-      type: "none";
-    }
-
-    interface BasicAuthFacadeCredentials {
-      type: "basic";
-
-      // Username to use to authenticate
-      username: string;
-
-      // Password to use to authenticate
-      password: string;
-    }
-
-    interface AccountAddResponse {
-      // Hash over the wire details (including over the salt).
-      h_wire: HashCode;
-
-      // Salt used to compute h_wire.
-      salt: HashCode;
-    }
-
-    interface AccountPatchDetails {
-
-      // URL from where the merchant can download information
-      // about incoming wire transfers to this account.
-      credit_facade_url?: string;
-
-      // Credentials to use when accessing the credit facade.
-      // Never returned on a GET (as this may be somewhat
-      // sensitive data). Can be set in POST
-      // or PATCH requests to update (or delete) credentials.
-      // To really delete credentials, set them to the type: "none".
-      credit_facade_credentials?: FacadeCredentials;
-    }
-
-
-    interface AccountsSummaryResponse {
-
-      // List of accounts that are known for the instance.
-      accounts: BankAccountEntry[];
-    }
-
-    interface BankAccountEntry {
-      // payto:// URI of the account.
-      payto_uri: string;
-
-      // Hash over the wire details (including over the salt)
-      h_wire: HashCode;
-
-      // salt used to compute h_wire
-      salt: HashCode;
-
-      // URL from where the merchant can download information
-      // about incoming wire transfers to this account.
-      credit_facade_url?: string;
-
-      // Credentials to use when accessing the credit facade.
-      // Never returned on a GET (as this may be somewhat
-      // sensitive data). Can be set in POST
-      // or PATCH requests to update (or delete) credentials.
-      credit_facade_credentials?: FacadeCredentials;
-
-      // true if this account is active,
-      // false if it is historic.
-      active: boolean;
-    }
-
-  }
-
-  namespace dead_Products {
-    // POST /private/products
-    interface ProductAddDetail {
-      // product ID to use.
-      product_id: string;
-
-      // Human-readable product description.
-      description: string;
-
-      // Map from IETF BCP 47 language tags to localized descriptions
-      description_i18n: { [lang_tag: string]: string };
-
-      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
-      unit: string;
-
-      // The price for one unit of the product. Zero is used
-      // to imply that this product is not sold separately, or
-      // that the price is not fixed, and must be supplied by the
-      // front-end.  If non-zero, this price MUST include applicable
-      // taxes.
-      price: Amount;
-
-      // An optional base64-encoded product image
-      image: ImageDataUrl;
-
-      // a list of taxes paid by the merchant for one unit of this product
-      taxes: Tax[];
-
-      // Number of units of the product in stock in sum in total,
-      // including all existing sales ever. Given in product-specific
-      // units.
-      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
-      total_stock: Integer;
-
-      // Identifies where the product is in stock.
-      address: Location;
-
-      // Identifies when we expect the next restocking to happen.
-      next_restock?: Timestamp;
-
-      // Minimum age buyer must have (in years). Default is 0.
-      minimum_age?: Integer;
-    }
-    //   PATCH /private/products/$PRODUCT_ID
-    interface ProductPatchDetail {
-      // Human-readable product description.
-      description: string;
-
-      // Map from IETF BCP 47 language tags to localized descriptions
-      description_i18n: { [lang_tag: string]: string };
-
-      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
-      unit: string;
-
-      // The price for one unit of the product. Zero is used
-      // to imply that this product is not sold separately, or
-      // that the price is not fixed, and must be supplied by the
-      // front-end.  If non-zero, this price MUST include applicable
-      // taxes.
-      price: Amount;
-
-      // An optional base64-encoded product image
-      image: ImageDataUrl;
-
-      // a list of taxes paid by the merchant for one unit of this product
-      taxes: Tax[];
-
-      // Number of units of the product in stock in sum in total,
-      // including all existing sales ever. Given in product-specific
-      // units.
-      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
-      total_stock: Integer;
-
-      // Number of units of the product that were lost (spoiled, stolen, etc.)
-      total_lost: Integer;
-
-      // Identifies where the product is in stock.
-      address: Location;
-
-      // Identifies when we expect the next restocking to happen.
-      next_restock?: Timestamp;
-
-      // Minimum age buyer must have (in years). Default is 0.
-      minimum_age?: Integer;
-    }
-
-    // GET /private/products
-    interface InventorySummaryResponse {
-      // List of products that are present in the inventory
-      products: InventoryEntry[];
-    }
-    interface InventoryEntry {
-      // Product identifier, as found in the product.
-      product_id: string;
-    }
-
-    // GET /private/products/$PRODUCT_ID
-    interface ProductDetail {
-      // Human-readable product description.
-      description: string;
-
-      // Map from IETF BCP 47 language tags to localized descriptions
-      description_i18n: { [lang_tag: string]: string };
-
-      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
-      unit: string;
-
-      // The price for one unit of the product. Zero is used
-      // to imply that this product is not sold separately, or
-      // that the price is not fixed, and must be supplied by the
-      // front-end.  If non-zero, this price MUST include applicable
-      // taxes.
-      price: Amount;
-
-      // An optional base64-encoded product image
-      image: ImageDataUrl;
-
-      // a list of taxes paid by the merchant for one unit of this product
-      taxes: Tax[];
-
-      // Number of units of the product in stock in sum in total,
-      // including all existing sales ever. Given in product-specific
-      // units.
-      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
-      total_stock: Integer;
-
-      // Number of units of the product that have already been sold.
-      total_sold: Integer;
-
-      // Number of units of the product that were lost (spoiled, stolen, etc.)
-      total_lost: Integer;
-
-      // Identifies where the product is in stock.
-      address: Location;
-
-      // Identifies when we expect the next restocking to happen.
-      next_restock?: Timestamp;
-
-      // Minimum age buyer must have (in years). Default is 0.
-      minimum_age?: Integer;
-    }
-
-    // POST /private/products/$PRODUCT_ID/lock
-    interface LockRequest {
-      // UUID that identifies the frontend performing the lock
-      // It is suggested that clients use a timeflake for this,
-      // see https://github.com/anthonynsimon/timeflake
-      lock_uuid: UUID;
-
-      // How long does the frontend intend to hold the lock
-      duration: RelativeTime;
-
-      // How many units should be locked?
-      quantity: Integer;
-    }
-
-    //   DELETE /private/products/$PRODUCT_ID
-  }
-
-  namespace dead_Orders {
-    type MerchantOrderStatusResponse =
-      | CheckPaymentPaidResponse
-      | CheckPaymentClaimedResponse
-      | CheckPaymentUnpaidResponse;
-    interface CheckPaymentPaidResponse {
-      // The customer paid for this contract.
-      order_status: "paid";
-
-      // Was the payment refunded (even partially)?
-      refunded: boolean;
-
-      // True if there are any approved refunds that the wallet has
-      // not yet obtained.
-      refund_pending: boolean;
-
-      // Did the exchange wire us the funds?
-      wired: boolean;
-
-      // Total amount the exchange deposited into our bank account
-      // for this contract, excluding fees.
-      deposit_total: Amount;
-
-      // Numeric error code indicating errors the exchange
-      // encountered tracking the wire transfer for this purchase (before
-      // we even got to specific coin issues).
-      // 0 if there were no issues.
-      exchange_ec: number;
-
-      // HTTP status code returned by the exchange when we asked for
-      // information to track the wire transfer for this purchase.
-      // 0 if there were no issues.
-      exchange_hc: number;
-
-      // Total amount that was refunded, 0 if refunded is false.
-      refund_amount: Amount;
-
-      // Contract terms.
-      contract_terms: ContractTerms;
-
-      // The wire transfer status from the exchange for this order if
-      // available, otherwise empty array.
-      wire_details: TransactionWireTransfer[];
-
-      // The refund details for this order.  One entry per
-      // refunded coin; empty array if there are no refunds.
-      refund_details: RefundDetails[];
-
-      // Status URL, can be used as a redirect target for the browser
-      // to show the order QR code / trigger the wallet.
-      order_status_url: string;
-    }
-    interface CheckPaymentClaimedResponse {
-      // A wallet claimed the order, but did not yet pay for the contract.
-      order_status: "claimed";
-
-      // Contract terms.
-      contract_terms: ContractTerms;
-    }
-    interface CheckPaymentUnpaidResponse {
-      // The order was neither claimed nor paid.
-      order_status: "unpaid";
-
-      // when was the order created
-      creation_time: Timestamp;
-
-      // Order summary text.
-      summary: string;
-
-      // Total amount of the order (to be paid by the customer).
-      total_amount: Amount;
-
-      // URI that the wallet must process to complete the payment.
-      taler_pay_uri: string;
-
-      // Alternative order ID which was paid for already in the same session.
-      // Only given if the same product was purchased before in the same 
session.
-      already_paid_order_id?: string;
-
-      // Fulfillment URL of an already paid order. Only given if under this
-      // session an already paid order with a fulfillment URL exists.
-      already_paid_fulfillment_url?: string;
-
-      // Status URL, can be used as a redirect target for the browser
-      // to show the order QR code / trigger the wallet.
-      order_status_url: string;
-
-      // We do we NOT return the contract terms here because they may not
-      // exist in case the wallet did not yet claim them.
-    }
-    interface RefundDetails {
-      // Reason given for the refund.
-      reason: string;
-
-      // When was the refund approved.
-      timestamp: Timestamp;
-
-      // Set to true if a refund is still available for the wallet for this 
payment.
-      pending: boolean;
-
-      // Total amount that was refunded (minus a refund fee).
-      amount: Amount;
-    }
-    interface TransactionWireTransfer {
-      // Responsible exchange.
-      exchange_url: string;
-
-      // 32-byte wire transfer identifier.
-      wtid: Base32;
-
-      // Execution time of the wire transfer.
-      execution_time: Timestamp;
-
-      // Total amount that has been wire transferred
-      // to the merchant.
-      amount: Amount;
-
-      // Was this transfer confirmed by the merchant via the
-      // POST /transfers API, or is it merely claimed by the exchange?
-      confirmed: boolean;
-    }
-    interface TransactionWireReport {
-      // Numerical error code.
-      code: number;
-
-      // Human-readable error description.
-      hint: string;
-
-      // Numerical error code from the exchange.
-      exchange_ec: number;
-
-      // HTTP status code received from the exchange.
-      exchange_hc: number;
-
-      // Public key of the coin for which we got the exchange error.
-      coin_pub: CoinPublicKey;
-    }
-
-    interface OrderHistory {
-      // timestamp-sorted array of all orders matching the query.
-      // The order of the sorting depends on the sign of delta.
-      orders: OrderHistoryEntry[];
-    }
-    interface OrderHistoryEntry {
-      // order ID of the transaction related to this entry.
-      order_id: string;
-
-      // row ID of the order in the database
-      row_id: number;
-
-      // when the order was created
-      timestamp: Timestamp;
-
-      // the amount of money the order is for
-      amount: Amount;
-
-      // the summary of the order
-      summary: string;
-
-      // whether some part of the order is refundable,
-      // that is the refund deadline has not yet expired
-      // and the total amount refunded so far is below
-      // the value of the original transaction.
-      refundable: boolean;
-
-      // whether the order has been paid or not
-      paid: boolean;
-    }
-
-    interface PostOrderRequest {
-      // The order must at least contain the minimal
-      // order detail, but can override all
-      order: Order;
-
-      // if set, the backend will then set the refund deadline to the current
-      // time plus the specified delay.  If it's not set, refunds will not be
-      // possible.
-      refund_delay?: RelativeTime;
-
-      // specifies the payment target preferred by the client. Can be used
-      // to select among the various (active) wire methods supported by the 
instance.
-      payment_target?: string;
-
-      // specifies that some products are to be included in the
-      // order from the inventory.  For these inventory management
-      // is performed (so the products must be in stock) and
-      // details are completed from the product data of the backend.
-      inventory_products?: MinimalInventoryProduct[];
-
-      // Specifies a lock identifier that was used to
-      // lock a product in the inventory.  Only useful if
-      // manage_inventory is set.  Used in case a frontend
-      // reserved quantities of the individual products while
-      // the shopping card was being built.  Multiple UUIDs can
-      // be used in case different UUIDs were used for different
-      // products (i.e. in case the user started with multiple
-      // shopping sessions that were combined during checkout).
-      lock_uuids?: UUID[];
-
-      // Should a token for claiming the order be generated?
-      // False can make sense if the ORDER_ID is sufficiently
-      // high entropy to prevent adversarial claims (like it is
-      // if the backend auto-generates one). Default is 'true'.
-      create_token?: boolean;
-
-      // OTP device ID to associate with the order.
-      // This parameter is optional.
-      otp_id?: string;
-    }
-    type Order = MinimalOrderDetail | ContractTerms;
-
-    interface MinimalOrderDetail {
-      // Amount to be paid by the customer
-      amount: Amount;
-
-      // Short summary of the order
-      summary: string;
-
-      // URL that will show that the order was successful after
-      // it has been paid for.  Optional. When POSTing to the
-      // merchant, the placeholder "${ORDER_ID}" will be
-      // replaced with the actual order ID (useful if the
-      // order ID is generated server-side and needs to be
-      // in the URL).
-      fulfillment_url?: string;
-    }
-
-    interface MinimalInventoryProduct {
-      // Which product is requested (here mandatory!)
-      product_id: string;
-
-      // How many units of the product are requested
-      quantity: Integer;
-    }
-    interface PostOrderResponse {
-      // Order ID of the response that was just created
-      order_id: string;
-
-      // Token that authorizes the wallet to claim the order.
-      // Provided only if "create_token" was set to 'true'
-      // in the request.
-      token?: ClaimToken;
-    }
-    interface OutOfStockResponse {
-      // Product ID of an out-of-stock item
-      product_id: string;
-
-      // Requested quantity
-      requested_quantity: Integer;
-
-      // Available quantity (must be below requested_quanitity)
-      available_quantity: Integer;
-
-      // When do we expect the product to be again in stock?
-      // Optional, not given if unknown.
-      restock_expected?: Timestamp;
-    }
-
-    interface ForgetRequest {
-      // Array of valid JSON paths to forgettable fields in the order's
-      // contract terms.
-      fields: string[];
-    }
-    interface RefundRequest {
-      // Amount to be refunded
-      refund: Amount;
-
-      // Human-readable refund justification
-      reason: string;
-    }
-    interface MerchantRefundResponse {
-      // URL (handled by the backend) that the wallet should access to
-      // trigger refund processing.
-      // taler://refund/...
-      taler_refund_uri: string;
-
-      // Contract hash that a client may need to authenticate an
-      // HTTP request to obtain the above URI in a wallet-friendly way.
-      h_contract: HashCode;
-    }
-  }
-
-  namespace dead_Rewards {
-    // GET /private/reserves
-    interface RewardReserveStatus {
-      // Array of all known reserves (possibly empty!)
-      reserves: ReserveStatusEntry[];
-    }
-    interface ReserveStatusEntry {
-      // Public key of the reserve
-      reserve_pub: EddsaPublicKey;
-
-      // Timestamp when it was established
-      creation_time: Timestamp;
-
-      // Timestamp when it expires
-      expiration_time: Timestamp;
-
-      // Initial amount as per reserve creation call
-      merchant_initial_amount: Amount;
-
-      // Initial amount as per exchange, 0 if exchange did
-      // not confirm reserve creation yet.
-      exchange_initial_amount: Amount;
-
-      // Amount picked up so far.
-      pickup_amount: Amount;
-
-      // Amount approved for rewards that exceeds the pickup_amount.
-      committed_amount: Amount;
-
-      // Is this reserve active (false if it was deleted but not purged)
-      active: boolean;
-    }
-
-    interface ReserveCreateRequest {
-      // Amount that the merchant promises to put into the reserve
-      initial_balance: Amount;
-
-      // Exchange the merchant intends to use for reward
-      exchange_url: string;
-
-      // Desired wire method, for example "iban" or "x-taler-bank"
-      wire_method: string;
-    }
-    interface ReserveCreateConfirmation {
-      // Public key identifying the reserve
-      reserve_pub: EddsaPublicKey;
-
-      // Wire accounts of the exchange where to transfer the funds.
-      accounts: WireAccount[];
-    }
-    interface RewardCreateRequest {
-      // Amount that the customer should be reward
-      amount: Amount;
-
-      // Justification for giving the reward
-      justification: string;
-
-      // URL that the user should be directed to after rewarding,
-      // will be included in the reward_token.
-      next_url: string;
-    }
-    interface RewardCreateConfirmation {
-      // Unique reward identifier for the reward that was created.
-      reward_id: HashCode;
-
-      // taler://reward URI for the reward
-      taler_reward_uri: string;
-
-      // URL that will directly trigger processing
-      // the reward when the browser is redirected to it
-      reward_status_url: string;
-
-      // when does the reward expire
-      reward_expiration: Timestamp;
-    }
-
-    interface ReserveDetail {
-      // Timestamp when it was established.
-      creation_time: Timestamp;
-
-      // Timestamp when it expires.
-      expiration_time: Timestamp;
-
-      // Initial amount as per reserve creation call.
-      merchant_initial_amount: Amount;
-
-      // Initial amount as per exchange, 0 if exchange did
-      // not confirm reserve creation yet.
-      exchange_initial_amount: Amount;
-
-      // Amount picked up so far.
-      pickup_amount: Amount;
-
-      // Amount approved for rewards that exceeds the pickup_amount.
-      committed_amount: Amount;
-
-      // Array of all rewards created by this reserves (possibly empty!).
-      // Only present if asked for explicitly.
-      rewards?: RewardStatusEntry[];
-
-      // Is this reserve active (false if it was deleted but not purged)?
-      active: boolean;
-
-      // Array of wire accounts of the exchange that could
-      // be used to fill the reserve, can be NULL
-      // if the reserve is inactive or was already filled
-      accounts?: WireAccount[];
-
-      // URL of the exchange hosting the reserve,
-      // NULL if the reserve is inactive
-      exchange_url: string;
-    }
-
-    interface RewardStatusEntry {
-      // Unique identifier for the reward.
-      reward_id: HashCode;
-
-      // Total amount of the reward that can be withdrawn.
-      total_amount: Amount;
-
-      // Human-readable reason for why the reward was granted.
-      reason: string;
-    }
-
-    interface RewardDetails {
-      // Amount that we authorized for this reward.
-      total_authorized: Amount;
-
-      // Amount that was picked up by the user already.
-      total_picked_up: Amount;
-
-      // Human-readable reason given when authorizing the reward.
-      reason: string;
-
-      // Timestamp indicating when the reward is set to expire (may be in the 
past).
-      expiration: Timestamp;
-
-      // Reserve public key from which the reward is funded.
-      reserve_pub: EddsaPublicKey;
-
-      // Array showing the pickup operations of the wallet (possibly empty!).
-      // Only present if asked for explicitly.
-      pickups?: PickupDetail[];
-    }
-    interface PickupDetail {
-      // Unique identifier for the pickup operation.
-      pickup_id: HashCode;
-
-      // Number of planchets involved.
-      num_planchets: Integer;
-
-      // Total amount requested for this pickup_id.
-      requested_amount: Amount;
-    }
-  }
-
-  namespace dead_Transfers {
-    interface TransferList {
-      // list of all the transfers that fit the filter that we know
-      transfers: TransferDetails[];
-    }
-    interface TransferDetails {
-      // how much was wired to the merchant (minus fees)
-      credit_amount: Amount;
-
-      // raw wire transfer identifier identifying the wire transfer (a 
base32-encoded value)
-      wtid: string;
-
-      // target account that received the wire transfer
-      payto_uri: string;
-
-      // base URL of the exchange that made the wire transfer
-      exchange_url: string;
-
-      // Serial number identifying the transfer in the merchant backend.
-      // Used for filgering via offset.
-      transfer_serial_id: number;
-
-      // Time of the execution of the wire transfer by the exchange, according 
to the exchange
-      // Only provided if we did get an answer from the exchange.
-      execution_time?: Timestamp;
-
-      // True if we checked the exchange's answer and are happy with it.
-      // False if we have an answer and are unhappy, missing if we
-      // do not have an answer from the exchange.
-      verified?: boolean;
-
-      // True if the merchant uses the POST /transfers API to confirm
-      // that this wire transfer took place (and it is thus not
-      // something merely claimed by the exchange).
-      confirmed?: boolean;
-    }
-
-    interface TransferInformation {
-      // how much was wired to the merchant (minus fees)
-      credit_amount: Amount;
-
-      // raw wire transfer identifier identifying the wire transfer (a 
base32-encoded value)
-      wtid: WireTransferIdentifierRawP;
-
-      // target account that received the wire transfer
-      payto_uri: string;
-
-      // base URL of the exchange that made the wire transfer
-      exchange_url: string;
-    }
-  }
-
-  namespace dead_OTP {
-    interface OtpDeviceAddDetails {
-      // Device ID to use.
-      otp_device_id: string;
-
-      // Human-readable description for the device.
-      otp_device_description: string;
-
-      // A base64-encoded key
-      otp_key: string;
-
-      // Algorithm for computing the POS confirmation.
-      otp_algorithm: Integer;
-
-      // Counter for counter-based OTP devices.
-      otp_ctr?: Integer;
-    }
-
-    interface OtpDevicePatchDetails {
-      // Human-readable description for the device.
-      otp_device_description: string;
-
-      // A base64-encoded key
-      otp_key: string | undefined;
-
-      // Algorithm for computing the POS confirmation.
-      otp_algorithm: Integer;
-
-      // Counter for counter-based OTP devices.
-      otp_ctr?: Integer;
-    }
-
-    interface OtpDeviceSummaryResponse {
-      // Array of devices that are present in our backend.
-      otp_devices: OtpDeviceEntry[];
-    }
-    interface OtpDeviceEntry {
-      // Device identifier.
-      otp_device_id: string;
-
-      // Human-readable description for the device.
-      device_description: string;
-    }
-
-    interface OtpDeviceDetails {
-      // Human-readable description for the device.
-      device_description: string;
-
-      // Algorithm for computing the POS confirmation.
-      otp_algorithm: Integer;
-
-      // Counter for counter-based OTP devices.
-      otp_ctr?: Integer;
-    }
-
-
-  }
-  namespace dead_Template {
-    interface TemplateAddDetails {
-      // Template ID to use.
-      template_id: string;
-
-      // Human-readable description for the template.
-      template_description: string;
-
-      // OTP device ID.
-      // This parameter is optional.
-      otp_id?: string;
-
-      // Additional information in a separate template.
-      template_contract: TemplateContractDetails;
-    }
-    interface TemplateContractDetails {
-      // Human-readable summary for the template.
-      summary?: string;
-
-      // The price is imposed by the merchant and cannot be changed by the 
customer.
-      // This parameter is optional.
-      amount?: Amount;
-
-      // Minimum age buyer must have (in years). Default is 0.
-      minimum_age: Integer;
-
-      // The time the customer need to pay before his order will be deleted.
-      // It is deleted if the customer did not pay and if the duration is over.
-      pay_duration: RelativeTime;
-    }
-    interface TemplatePatchDetails {
-      // Human-readable description for the template.
-      template_description: string;
-
-      // OTP device ID.
-      // This parameter is optional.
-      otp_id?: string;
-
-      // Additional information in a separate template.
-      template_contract: TemplateContractDetails;
-    }
-
-    interface TemplateSummaryResponse {
-      // List of templates that are present in our backend.
-      templates: TemplateEntry[];
-    }
-
-    interface TemplateEntry {
-      // Template identifier, as found in the template.
-      template_id: string;
-
-      // Human-readable description for the template.
-      template_description: string;
-    }
-
-    interface TemplateDetails {
-      // Human-readable description for the template.
-      template_description: string;
-
-      // OTP device ID.
-      // This parameter is optional.
-      otp_id?: string;
-
-      // Additional information in a separate template.
-      template_contract: TemplateContractDetails;
-    }
-
-    interface UsingTemplateDetails {
-      // Subject of the template
-      summary?: string;
-
-      // The amount entered by the customer.
-      amount?: Amount;
-    }
-
-    interface UsingTemplateResponse {
-      // After enter the request. The user will be pay with a taler URL.
-      order_id: string;
-      token: string;
-    }
-  }
-
-  namespace dead_Webhooks {
-    type MerchantWebhookType = "pay" | "refund";
-    interface WebhookAddDetails {
-      // Webhook ID to use.
-      webhook_id: string;
-
-      // The event of the webhook: why the webhook is used.
-      event_type: MerchantWebhookType;
-
-      // URL of the webhook where the customer will be redirected.
-      url: string;
-
-      // Method used by the webhook
-      http_method: string;
-
-      // Header template of the webhook
-      header_template?: string;
-
-      // Body template by the webhook
-      body_template?: string;
-    }
-    interface WebhookPatchDetails {
-      // The event of the webhook: why the webhook is used.
-      event_type: string;
-
-      // URL of the webhook where the customer will be redirected.
-      url: string;
-
-      // Method used by the webhook
-      http_method: string;
-
-      // Header template of the webhook
-      header_template?: string;
-
-      // Body template by the webhook
-      body_template?: string;
-    }
-    interface WebhookSummaryResponse {
-      // List of webhooks that are present in our backend.
-      webhooks: WebhookEntry[];
-    }
-    interface WebhookEntry {
-      // Webhook identifier, as found in the webhook.
-      webhook_id: string;
-
-      // The event of the webhook: why the webhook is used.
-      event_type: string;
-    }
-    interface WebhookDetails {
-      // The event of the webhook: why the webhook is used.
-      event_type: string;
-
-      // URL of the webhook where the customer will be redirected.
-      url: string;
-
-      // Method used by the webhook
-      http_method: string;
-
-      // Header template of the webhook
-      header_template?: string;
-
-      // Body template by the webhook
-      body_template?: string;
-    }
-  }
-
-  interface ContractTerms {
-    // Human-readable description of the whole purchase
-    summary: string;
-
-    // Map from IETF BCP 47 language tags to localized summaries
-    summary_i18n?: { [lang_tag: string]: string };
-
-    // Unique, free-form identifier for the proposal.
-    // Must be unique within a merchant instance.
-    // For merchants that do not store proposals in their DB
-    // before the customer paid for them, the order_id can be used
-    // by the frontend to restore a proposal from the information
-    // encoded in it (such as a short product identifier and timestamp).
-    order_id: string;
-
-    // Total price for the transaction.
-    // The exchange will subtract deposit fees from that amount
-    // before transferring it to the merchant.
-    amount: Amount;
-
-    // The URL for this purchase.  Every time is is visited, the merchant
-    // will send back to the customer the same proposal.  Clearly, this URL
-    // can be bookmarked and shared by users.
-    fulfillment_url?: string;
-
-    // Maximum total deposit fee accepted by the merchant for this contract
-    max_fee: Amount;
-
-    // List of products that are part of the purchase (see Product).
-    products: Product[];
-
-    // Time when this contract was generated
-    timestamp: TalerProtocolTimestamp;
-
-    // After this deadline has passed, no refunds will be accepted.
-    refund_deadline: TalerProtocolTimestamp;
-
-    // After this deadline, the merchant won't accept payments for the contact
-    pay_deadline: TalerProtocolTimestamp;
-
-    // Transfer deadline for the exchange.  Must be in the
-    // deposit permissions of coins used to pay for this order.
-    wire_transfer_deadline: TalerProtocolTimestamp;
-
-    // Merchant's public key used to sign this proposal; this information
-    // is typically added by the backend Note that this can be an ephemeral 
key.
-    merchant_pub: EddsaPublicKey;
-
-    // Base URL of the (public!) merchant backend API.
-    // Must be an absolute URL that ends with a slash.
-    merchant_base_url: string;
-
-    // More info about the merchant, see below
-    merchant: Merchant;
-
-    // The hash of the merchant instance's wire details.
-    h_wire: HashCode;
-
-    // Wire transfer method identifier for the wire method associated with 
h_wire.
-    // The wallet may only select exchanges via a matching auditor if the
-    // exchange also supports this wire method.
-    // The wire transfer fees must be added based on this wire transfer method.
-    wire_method: string;
-
-    // Any exchanges audited by these auditors are accepted by the merchant.
-    auditors: Auditor[];
-
-    // Exchanges that the merchant accepts even if it does not accept any 
auditors that audit them.
-    exchanges: Exchange[];
-
-    // Delivery location for (all!) products.
-    delivery_location?: Location;
-
-    // Time indicating when the order should be delivered.
-    // May be overwritten by individual products.
-    delivery_date?: TalerProtocolTimestamp;
-
-    // Nonce generated by the wallet and echoed by the merchant
-    // in this field when the proposal is generated.
-    nonce: string;
-
-    // Specifies for how long the wallet should try to get an
-    // automatic refund for the purchase. If this field is
-    // present, the wallet should wait for a few seconds after
-    // the purchase and then automatically attempt to obtain
-    // a refund.  The wallet should probe until "delay"
-    // after the payment was successful (i.e. via long polling
-    // or via explicit requests with exponential back-off).
-    //
-    // In particular, if the wallet is offline
-    // at that time, it MUST repeat the request until it gets
-    // one response from the merchant after the delay has expired.
-    // If the refund is granted, the wallet MUST automatically
-    // recover the payment.  This is used in case a merchant
-    // knows that it might be unable to satisfy the contract and
-    // desires for the wallet to attempt to get the refund without any
-    // customer interaction.  Note that it is NOT an error if the
-    // merchant does not grant a refund.
-    auto_refund?: RelativeTime;
-
-    // Extra data that is only interpreted by the merchant frontend.
-    // Useful when the merchant needs to store extra information on a
-    // contract without storing it separately in their database.
-    extra?: any;
-
-    // Minimum age buyer must have (in years). Default is 0.
-    minimum_age?: Integer;
-  }
-}
diff --git a/packages/merchant-backoffice-ui/src/hooks/backend.ts 
b/packages/merchant-backoffice-ui/src/hooks/backend.ts
index 8eb9b4cf2..e4e50c8ad 100644
--- a/packages/merchant-backoffice-ui/src/hooks/backend.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/backend.ts
@@ -177,16 +177,6 @@ interface useBackendBaseRequestType {
 }
 
 type YesOrNo = "yes" | "no";
-type LoginResult =
-  | {
-      valid: true;
-      token: string;
-      expiration: Timestamp;
-    }
-  | {
-      valid: false;
-      cause: HttpError<EmptyObject>;
-    };
 
 /**
  *
diff --git a/packages/merchant-backoffice-ui/src/hooks/instance.test.ts 
b/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
index 35147d988..3b02d7758 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.test.ts
@@ -19,15 +19,12 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { AccessToken, TalerMerchantApi } from "@gnu-taler/taler-util";
+import { TalerMerchantApi } from "@gnu-taler/taler-util";
 import * as tests from "@gnu-taler/web-util/testing";
 import { expect } from "chai";
 import {
-  useAdminAPI,
   useBackendInstances,
-  useInstanceAPI,
   useInstanceDetails,
-  useManagementAPI,
 } from "./instance.js";
 import { ApiMockEnvironment } from "./testing.js";
 import {
@@ -39,6 +36,7 @@ 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 () => {
@@ -52,7 +50,8 @@ describe("instance api interaction with details", () => {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useInstanceAPI();
+        // const api = useInstanceAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useInstanceDetails();
         return { query, api };
       },
@@ -82,7 +81,7 @@ describe("instance api interaction with details", () => {
               name: "other_name",
             } as TalerMerchantApi.QueryInstancesResponse,
           });
-          api.updateInstance({
+          api.management.updateCurrentInstance(undefined, {
             name: "other_name",
           } as TalerMerchantApi.InstanceReconfigurationMessage);
         },
@@ -120,7 +119,7 @@ describe("instance api interaction with details", () => {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useInstanceAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useInstanceDetails();
         return { query, api };
       },
@@ -206,7 +205,7 @@ describe("instance api interaction with details", () => {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useInstanceAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useInstanceDetails();
         return { query, api };
       },
@@ -243,7 +242,9 @@ describe("instance api interaction with details", () => {
             } as TalerMerchantApi.QueryInstancesResponse,
           });
 
-          api.clearAccessToken(undefined);
+          api.management.updateCurrentInstanceAuthentication(undefined, {
+            method: "external"
+          });
         },
         ({ query, api }) => {
           expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -337,7 +338,7 @@ describe("instance admin api interaction with listing", () 
=> {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useAdminAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useBackendInstances();
         return { query, api };
       },
@@ -379,9 +380,9 @@ describe("instance admin api interaction with listing", () 
=> {
             },
           });
 
-          api.createInstance({
+          api.management.createInstance(undefined, {
             name: "other_name",
-          } as TalerMerchantApi.InstanceConfigurationMessage);
+          } as TalerMerchantApi.InstanceConfigurationMessage)
         },
         ({ query, api }) => {
           expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -428,7 +429,7 @@ describe("instance admin api interaction with listing", () 
=> {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useAdminAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useBackendInstances();
         return { query, api };
       },
@@ -469,7 +470,7 @@ describe("instance admin api interaction with listing", () 
=> {
             },
           });
 
-          api.deleteInstance("the_id");
+          api.management.deleteInstance(undefined, "the_id");
         },
         ({ query, api }) => {
           expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -582,7 +583,7 @@ describe("instance admin api interaction with listing", () 
=> {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useAdminAPI();
+        const { lib: api } = useMerchantApiContext()
         const query = useBackendInstances();
         return { query, api };
       },
@@ -627,7 +628,7 @@ describe("instance admin api interaction with listing", () 
=> {
             },
           });
 
-          api.purgeInstance("the_id");
+          api.management.deleteInstance(undefined, "the_id", { purge: true })
         },
         ({ query, api }) => {
           expect(env.assertJustExpectedRequestWereMade()).deep.eq({
@@ -670,7 +671,7 @@ describe("instance management api interaction with 
listing", () => {
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       () => {
-        const api = useManagementAPI("managed");
+        const { lib: api } = useMerchantApiContext()
         const query = useBackendInstances();
         return { query, api };
       },
@@ -711,7 +712,7 @@ describe("instance management api interaction with 
listing", () => {
             },
           });
 
-          api.updateInstance({
+          api.management.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 5f17dbf79..0ba68250a 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.ts
@@ -20,219 +20,14 @@ import {
 } from "@gnu-taler/web-util/browser";
 import {
   useBackendBaseRequest,
-  useBackendInstanceRequest,
-  useMatchMutate,
+  useBackendInstanceRequest
 } from "./backend.js";
 
 // FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import { AccessToken, TalerErrorDetail, TalerMerchantApi } from 
"@gnu-taler/taler-util";
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
-import { useSessionContext } from "../context/session.js";
+import { TalerErrorDetail, TalerMerchantApi } from "@gnu-taler/taler-util";
+import _useSWR, { SWRHook } from "swr";
 const useSWR = _useSWR as unknown as SWRHook;
 
-interface InstanceAPI {
-  updateInstance: (
-    data: TalerMerchantApi.InstanceReconfigurationMessage,
-  ) => Promise<void>;
-  deleteInstance: () => Promise<void>;
-  clearAccessToken: (currentToken: AccessToken | undefined) => Promise<void>;
-  // setNewAccessToken: (
-  //   currentToken: AccessToken | undefined,
-  //   token: AccessToken,
-  // ) => Promise<void>;
-}
-
-export function useAdminAPI(): AdminAPI {
-  const { request } = useBackendBaseRequest();
-  const mutateAll = useMatchMutate();
-
-  const createInstance = async (
-    instance: TalerMerchantApi.InstanceConfigurationMessage,
-  ): Promise<void> => {
-    await request(`/management/instances`, {
-      method: "POST",
-      data: instance,
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  const deleteInstance = async (id: string): Promise<void> => {
-    await request(`/management/instances/${id}`, {
-      method: "DELETE",
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  const purgeInstance = async (id: string): Promise<void> => {
-    await request(`/management/instances/${id}`, {
-      method: "DELETE",
-      params: {
-        purge: "YES",
-      },
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  return { createInstance, deleteInstance, purgeInstance };
-}
-
-export interface AdminAPI {
-  createInstance: (
-    data: TalerMerchantApi.InstanceConfigurationMessage,
-  ) => Promise<void>;
-  deleteInstance: (id: string) => Promise<void>;
-  purgeInstance: (id: string) => Promise<void>;
-}
-
-export function useManagementAPI(instanceId: string): InstanceAPI {
-  const mutateAll = useMatchMutate();
-  const {
-    state: { backendUrl },
-    logIn,
-    logOut,
-  } = useSessionContext();
-  const { request } = useBackendBaseRequest();
-
-  const updateInstance = async (
-    instance: TalerMerchantApi.InstanceReconfigurationMessage,
-  ): Promise<void> => {
-    await request(`/management/instances/${instanceId}`, {
-      method: "PATCH",
-      data: instance,
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  const deleteInstance = async (): Promise<void> => {
-    await request(`/management/instances/${instanceId}`, {
-      method: "DELETE",
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  const clearAccessToken = async (
-    currentToken: AccessToken | undefined,
-  ): Promise<void> => {
-    await request(`/management/instances/${instanceId}/auth`, {
-      method: "POST",
-      token: currentToken,
-      data: { method: "external" },
-    });
-
-    mutateAll(/\/management\/instances/);
-  };
-
-  // const setNewAccessToken = async (
-  //   currentToken: AccessToken | undefined,
-  //   newToken: AccessToken,
-  // ): Promise<void> => {
-
-  //   await request(`/management/instances/${instanceId}/auth`, {
-  //     method: "POST",
-  //     token: currentToken,
-  //     data: { method: "token", token: newToken },
-  //   });
-
-  //   const resp = await requestNewLoginToken(backendUrl, newToken);
-  //   if (resp.valid) {
-  //     logIn({ token: resp.token as AccessToken });
-  //   } else {
-  //     logOut();
-  //   }
-
-  //   mutateAll(/\/management\/instances/);
-  // };
-
-  return {
-    updateInstance,
-    deleteInstance,
-    // setNewAccessToken,
-    clearAccessToken,
-  };
-}
-
-export function useInstanceAPI(): InstanceAPI {
-  const { mutate } = useSWRConfig();
-  const {
-    state: { backendUrl },
-  } = useSessionContext();
-
-  const { request } = useBackendInstanceRequest();
-  const { state, logIn, logOut } = useSessionContext();
-
-  const adminToken =
-    state.status === "loggedIn" && state.isAdmin ? state.token : undefined;
-
-  const updateInstance = async (
-    instance: TalerMerchantApi.InstanceReconfigurationMessage,
-  ): Promise<void> => {
-    await request(`/private/`, {
-      method: "PATCH",
-      data: instance,
-    });
-
-    if (adminToken) {
-      mutate(["/private/instances", adminToken, backendUrl], null);
-    }
-    mutate([`/private/`], null);
-  };
-
-  const deleteInstance = async (): Promise<void> => {
-    await request(`/private/`, {
-      method: "DELETE",
-      // token: adminToken,
-    });
-
-    if (adminToken) {
-      mutate(["/private/instances", adminToken, backendUrl], null);
-    }
-    mutate([`/private/`], null);
-  };
-
-  const clearAccessToken = async (
-    currentToken: AccessToken | undefined,
-  ): Promise<void> => {
-    await request(`/private/auth`, {
-      method: "POST",
-      token: currentToken,
-      data: { method: "external" },
-    });
-
-    mutate([`/private/`], null);
-  };
-
-  // const setNewAccessToken = async (
-  //   currentToken: AccessToken | undefined,
-  //   newToken: AccessToken,
-  // ): Promise<void> => {
-  //   await request(`/private/auth`, {
-  //     method: "POST",
-  //     token: currentToken,
-  //     data: { method: "token", token: newToken },
-  //   });
-
-  //   const resp = await requestNewLoginToken(backendUrl, newToken);
-  //   if (resp.valid) {
-  //     logIn({ token: resp.token as AccessToken });
-  //   } else {
-  //     logOut();
-  //   }
-
-  //   mutate([`/private/`], null);
-  // };
-
-  return {
-    updateInstance,
-    deleteInstance,
-    // setNewAccessToken,
-    clearAccessToken,
-  };
-}
 
 export function useInstanceDetails(): HttpResponse<
   TalerMerchantApi.QueryInstancesResponse,
diff --git a/packages/merchant-backoffice-ui/src/hooks/templates.ts 
b/packages/merchant-backoffice-ui/src/hooks/templates.ts
index 2e39a0c46..2da02e3c7 100644
--- a/packages/merchant-backoffice-ui/src/hooks/templates.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/templates.ts
@@ -190,20 +190,20 @@ export function useInstanceTemplates(
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
-    afterData && afterData.data.templates_list.length < totalAfter;
+    afterData && afterData.data.templates.length < totalAfter;
   const isReachingStart = args?.position === undefined
     ||
-    (beforeData && beforeData.data.templates_list.length < totalBefore);
+    (beforeData && beforeData.data.templates.length < totalBefore);
 
   const pagination = {
     isReachingEnd,
     isReachingStart,
     loadMore: () => {
       if (!afterData || isReachingEnd) return;
-      if (afterData.data.templates_list.length < MAX_RESULT_SIZE) {
+      if (afterData.data.templates.length < MAX_RESULT_SIZE) {
         setPageAfter(pageAfter + 1);
       } else {
-        const from = 
`${afterData.data.templates_list[afterData.data.templates_list.length - 1]
+        const from = 
`${afterData.data.templates[afterData.data.templates.length - 1]
           .template_id
           }`;
         if (from && updatePosition) updatePosition(from);
@@ -211,10 +211,10 @@ export function useInstanceTemplates(
     },
     loadMorePrev: () => {
       if (!beforeData || isReachingStart) return;
-      if (beforeData.data.templates_list.length < MAX_RESULT_SIZE) {
+      if (beforeData.data.templates.length < MAX_RESULT_SIZE) {
         setPageBefore(pageBefore + 1);
       } else if (beforeData) {
-        const from = 
`${beforeData.data.templates_list[beforeData.data.templates_list.length - 1]
+        const from = 
`${beforeData.data.templates[beforeData.data.templates.length - 1]
           .template_id
           }`;
         if (from && updatePosition) updatePosition(from);
@@ -223,17 +223,17 @@ export function useInstanceTemplates(
   };
 
   // const templates = !afterData ? [] : (afterData || 
lastAfter).data.templates;
-  const templates_list =
+  const templates =
     !beforeData || !afterData
       ? []
-      : (beforeData || lastBefore).data.templates_list
+      : (beforeData || lastBefore).data.templates
         .slice()
         .reverse()
-        .concat((afterData || lastAfter).data.templates_list);
+        .concat((afterData || lastAfter).data.templates);
   if (loadingAfter || loadingBefore)
-    return { loading: true, data: { templates_list } };
+    return { loading: true, data: { templates } };
   if (beforeData && afterData) {
-    return { ok: true, data: { templates_list }, ...pagination };
+    return { ok: true, data: { templates }, ...pagination };
   }
   return { loading: true };
 }
diff --git 
a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx 
b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx
index 731ea8939..d53d93e8b 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx
@@ -123,7 +123,7 @@ export function CreatePage({ onCreate, onBack, forceId }: 
Props): VNode {
     newValue.auth_token = undefined;
     newValue.auth = newToken === null || newToken === undefined
       ? { method: "external" }
-      : { method: "token", token: `secret-token:${newToken}` };
+      : { method: "token", token: newToken };
     if (!newValue.address) newValue.address = {};
     if (!newValue.jurisdiction) newValue.jurisdiction = {};
     // remove above use conversion
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 0e8ea1f5b..431015d6f 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/create/index.tsx
@@ -26,7 +26,6 @@ import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { NotificationCard } from "../../../components/menu/index.js";
 import { useSessionContext } from "../../../context/session.js";
-import { useAdminAPI } from "../../../hooks/instance.js";
 import { Notification } from "../../../utils/types.js";
 import { CreatePage } from "./CreatePage.js";
 
@@ -38,11 +37,10 @@ interface Props {
 export type Entity = TalerMerchantApi.InstanceConfigurationMessage;
 
 export default function Create({ onBack, onConfirm, forceId }: Props): VNode {
-  const { createInstance } = useAdminAPI();
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
   const { i18n } = useTranslationContext();
   const { lib } = useMerchantApiContext();
-  const { logIn } = useSessionContext();
+  const { state, logIn } = useSessionContext();
 
   return (
     <Fragment>
@@ -54,9 +52,11 @@ export default function Create({ onBack, onConfirm, forceId 
}: Props): VNode {
         onCreate={async (
           d: TalerMerchantApi.InstanceConfigurationMessage,
         ) => {
+          if (state.status !== "loggedIn") return;
           try {
-            await createInstance(d);
+            await lib.management.createInstance(state.token, d);
             if (d.auth.token) {
+              //if auth has been updated, request a new access token
               const result = await lib.authenticate.createAccessTokenBearer(
                 d.auth.token,
                 {
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 d3fa78b65..5b8cf2a5c 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/index.tsx
@@ -23,6 +23,7 @@ import { HttpStatusCode, TalerErrorDetail, TalerMerchantApi } 
from "@gnu-taler/t
 import {
   ErrorType,
   HttpError,
+  useMerchantApiContext,
   useTranslationContext,
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
@@ -30,9 +31,10 @@ import { useState } from "preact/hooks";
 import { Loading } from "../../../components/exception/loading.js";
 import { NotificationCard } from "../../../components/menu/index.js";
 import { DeleteModal, PurgeModal } from "../../../components/modal/index.js";
-import { useAdminAPI, useBackendInstances } from "../../../hooks/instance.js";
+import { useBackendInstances } from "../../../hooks/instance.js";
 import { Notification } from "../../../utils/types.js";
 import { View } from "./View.js";
+import { useSessionContext } from "../../../context/session.js";
 
 interface Props {
   onCreate: () => void;
@@ -55,9 +57,10 @@ export default function Instances({
     useState<TalerMerchantApi.Instance | null>(null);
   const [purging, setPurging] =
     useState<TalerMerchantApi.Instance | null>(null);
-  const { deleteInstance, purgeInstance } = useAdminAPI();
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
   const { i18n } = useTranslationContext();
+  const { lib } = useMerchantApiContext();
+  const { state } = useSessionContext();
 
   if (result.loading) return <Loading />;
   if (!result.ok) {
@@ -90,9 +93,12 @@ export default function Instances({
           element={deleting}
           onCancel={() => setDeleting(null)}
           onConfirm={async (): Promise<void> => {
+            if (state.status !== "loggedIn") {
+              return;
+            }
             try {
-              await deleteInstance(deleting.id);
-              // pushNotification({ message: 'delete_success', type: 'SUCCESS' 
})
+              await lib.management.deleteInstance(state.token, deleting.id);
+              // pushNotification({message: 'delete_success', type: 'SUCCESS' 
})
               setNotif({
                 message: i18n.str`Instance "${deleting.name}" (ID: 
${deleting.id}) has been deleted`,
                 type: "SUCCESS",
@@ -103,7 +109,7 @@ export default function Instances({
                 type: "ERROR",
                 description: error instanceof Error ? error.message : 
undefined,
               });
-              // pushNotification({ message: 'delete_error', type: 'ERROR' })
+              // pushNotification({message: 'delete_error', type: 'ERROR' })
             }
             setDeleting(null);
           }}
@@ -114,8 +120,11 @@ export default function Instances({
           element={purging}
           onCancel={() => setPurging(null)}
           onConfirm={async (): Promise<void> => {
+            if (state.status !== "loggedIn") {
+              return;
+            }
             try {
-              await purgeInstance(purging.id);
+              await lib.management.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/details/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
index b76abee30..2714c8e02 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/details/index.tsx
@@ -13,12 +13,12 @@
  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 { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { ErrorType, HttpError, useMerchantApiContext } from 
"@gnu-taler/web-util/browser";
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { Loading } from "../../../components/exception/loading.js";
 import { DeleteModal } from "../../../components/modal/index.js";
-import { useInstanceAPI, useInstanceDetails } from 
"../../../hooks/instance.js";
+import { useInstanceDetails } from "../../../hooks/instance.js";
 import { DetailPage } from "./DetailPage.js";
 import { HttpStatusCode, TalerErrorDetail } from "@gnu-taler/taler-util";
 import { useSessionContext } from "../../../context/session.js";
@@ -42,7 +42,8 @@ export default function Detail({
   const result = useInstanceDetails();
   const [deleting, setDeleting] = useState<boolean>(false);
 
-  const { deleteInstance } = useInstanceAPI();
+  // const { deleteInstance } = useInstanceAPI();
+  const { lib } = useMerchantApiContext();
 
   if (result.loading) return <Loading />;
   if (!result.ok) {
@@ -71,8 +72,11 @@ export default function Detail({
           element={{ name: result.data.name, id: state.instance }}
           onCancel={() => setDeleting(false)}
           onConfirm={async (): Promise<void> => {
+            if (state.status !== "loggedIn") {
+              return
+            }
             try {
-              await deleteInstance();
+              await lib.management.deleteCurrentInstance(state.token);
               onDelete();
             } catch (error) {
               //FIXME: show message error
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 2138d24a4..40ca6ac98 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
@@ -92,7 +92,7 @@ export default function ListTemplates({
       />
 
       <ListPage
-        templates={result.data.templates_list}
+        templates={result.data.templates}
         onLoadMoreBefore={
           result.isReachingStart ? result.loadMorePrev : undefined
         }
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
index f2b1db29b..c833b908c 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/DetailPage.tsx
@@ -77,9 +77,9 @@ export function DetailPage({
   async function submitForm() {
     if (hasErrors) return;
     const oldToken = hasToken
-      ? (`secret-token:${form.old_token}` as AccessToken)
+      ? (form.old_token as AccessToken)
       : undefined;
-    const newToken = `secret-token:${form.new_token}` as AccessToken;
+    const newToken = form.new_token as AccessToken;
     onNewToken(oldToken, newToken);
   }
 
@@ -133,8 +133,7 @@ export function DetailPage({
                         class="button"
                         onClick={() => {
                           if (hasToken) {
-                            const oldToken =
-                              `secret-token:${form.old_token}` as AccessToken;
+                            const oldToken = form.old_token as AccessToken;
                             onClearToken(oldToken);
                           } else {
                             onClearToken(undefined);
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 13b5c45f1..f3c9a52ea 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/token/index.tsx
@@ -13,16 +13,16 @@
  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 { AccessToken, HttpStatusCode, TalerErrorDetail } from 
"@gnu-taler/taler-util";
+import { HttpStatusCode, TalerErrorDetail } from "@gnu-taler/taler-util";
 import { ErrorType, HttpError, useMerchantApiContext, useTranslationContext } 
from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { Loading } from "../../../components/exception/loading.js";
 import { NotificationCard } from "../../../components/menu/index.js";
-import { useInstanceAPI, useInstanceDetails } from 
"../../../hooks/instance.js";
+import { useSessionContext } from "../../../context/session.js";
+import { useInstanceDetails } from "../../../hooks/instance.js";
 import { Notification } from "../../../utils/types.js";
 import { DetailPage } from "./DetailPage.js";
-import { useSessionContext } from "../../../context/session.js";
 
 interface Props {
   onUnauthorized: () => VNode;
@@ -43,7 +43,7 @@ export default function Token({
   const { lib } = useMerchantApiContext();
   const { logIn } = useSessionContext();
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
-  const { clearAccessToken } = useInstanceAPI();
+  // const { clearAccessToken } = useInstanceAPI();
   const result = useInstanceDetails()
 
   if (result.loading) return <Loading />;
@@ -71,7 +71,9 @@ export default function Token({
         hasToken={hasToken}
         onClearToken={async (currentToken): Promise<void> => {
           try {
-            await clearAccessToken(currentToken);
+            await 
lib.management.updateCurrentInstanceAuthentication(currentToken, {
+              method: "external",
+            })
             onChange();
           } catch (error) {
             if (error instanceof 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 d28ca0555..32e4e149c 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/update/index.tsx
@@ -13,11 +13,12 @@
  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, TalerErrorDetail, TalerMerchantApi } from 
"@gnu-taler/taler-util";
+import { HttpStatusCode, TalerErrorDetail, TalerMerchantApi, 
TalerMerchantInstanceHttpClient } from "@gnu-taler/taler-util";
 import {
   ErrorType,
   HttpError,
   HttpResponse,
+  useMerchantApiContext,
   useTranslationContext,
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
@@ -25,13 +26,12 @@ import { useState } from "preact/hooks";
 import { Loading } from "../../../components/exception/loading.js";
 import { NotificationCard } from "../../../components/menu/index.js";
 import {
-  useInstanceAPI,
   useInstanceDetails,
   useManagedInstanceDetails,
-  useManagementAPI,
 } from "../../../hooks/instance.js";
 import { Notification } from "../../../utils/types.js";
 import { UpdatePage } from "./UpdatePage.js";
+import { useSessionContext } from "../../../context/session.js";
 
 export interface Props {
   onBack: () => void;
@@ -44,19 +44,21 @@ export interface Props {
 }
 
 export default function Update(props: Props): VNode {
-  const { updateInstance } = useInstanceAPI();
+  const { lib } = useMerchantApiContext();
+  const updateInstance = 
lib.management.updateCurrentInstance.bind(lib.management)
   const result = useInstanceDetails();
-  return CommonUpdate(props, result, updateInstance, );
+  return CommonUpdate(props, result, updateInstance,);
 }
 
 export function AdminUpdate(props: Props & { instanceId: string }): VNode {
-  const { updateInstance } = useManagementAPI(
-    props.instanceId,
-  );
+  const { lib } = useMerchantApiContext();
+  const t = lib.instance(props.instanceId)
+  const updateInstance = 
lib.instance(props.instanceId).updateCurrentInstance.bind(t)
   const result = useManagedInstanceDetails(props.instanceId);
-  return CommonUpdate(props, result, updateInstance, );
+  return CommonUpdate(props, result, updateInstance,);
 }
 
+
 function CommonUpdate(
   {
     onBack,
@@ -69,10 +71,11 @@ function CommonUpdate(
     TalerMerchantApi.QueryInstancesResponse,
     TalerErrorDetail
   >,
-  updateInstance: any,
+  updateInstance: typeof 
TalerMerchantInstanceHttpClient.prototype.updateCurrentInstance,
 ): VNode {
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
   const { i18n } = useTranslationContext();
+  const { state } = useSessionContext();
 
   if (result.loading) return <Loading />;
   if (!result.ok) {
@@ -99,11 +102,14 @@ function CommonUpdate(
         onUpdate={(
           d: TalerMerchantApi.InstanceReconfigurationMessage,
         ): Promise<void> => {
-          return updateInstance(d)
+          if (state.status !== "loggedIn") {
+            return Promise.resolve();
+          }
+          return updateInstance(state.token, d)
             .then(onConfirm)
             .catch((error: Error) =>
               setNotif({
-                message: i18n.str`Failed to create instance`,
+                message: i18n.str`Failed to update instance`,
                 type: "ERROR",
                 description: error.message,
               }),
diff --git a/packages/taler-util/src/http-client/merchant.ts 
b/packages/taler-util/src/http-client/merchant.ts
index 394625e38..fec1e7143 100644
--- a/packages/taler-util/src/http-client/merchant.ts
+++ b/packages/taler-util/src/http-client/merchant.ts
@@ -385,7 +385,7 @@ export class TalerMerchantInstanceHttpClient {
       headers,
     });
     switch (resp.status) {
-      case HttpStatusCode.Ok:
+      case HttpStatusCode.NoContent:
         return opEmptySuccess(resp);
       case HttpStatusCode.NotFound:
         return opKnownHttpFailure(resp.status, resp);
@@ -421,7 +421,7 @@ export class TalerMerchantInstanceHttpClient {
   /**
    * 
https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private
    */
-  async deleteCurrentInstance(token: AccessToken | undefined, params: { 
purge?: boolean }) {
+  async deleteCurrentInstance(token: AccessToken | undefined, params: { 
purge?: boolean } = {}) {
     const url = new URL(`private`, this.baseUrl);
 
     if (params.purge) {
diff --git a/packages/taler-util/src/http-client/types.ts 
b/packages/taler-util/src/http-client/types.ts
index 8578eecd4..682b08984 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -801,7 +801,7 @@ export const codecForOtpDeviceDetails =
 export const codecForTemplateSummaryResponse =
   (): Codec<TalerMerchantApi.TemplateSummaryResponse> =>
     buildCodecForObject<TalerMerchantApi.TemplateSummaryResponse>()
-      .property("templates_list", codecForList(codecForTemplateEntry()))
+      .property("templates", codecForList(codecForTemplateEntry()))
       .build("TalerMerchantApi.TemplateSummaryResponse");
 
 export const codecForTemplateEntry =
@@ -4606,7 +4606,7 @@ export namespace TalerMerchantApi {
 
   export interface TemplateSummaryResponse {
     // List of templates that are present in our backend.
-    templates_list: TemplateEntry[];
+    templates: TemplateEntry[];
   }
 
   export interface TemplateEntry {
diff --git a/packages/web-util/src/context/merchant-api.ts 
b/packages/web-util/src/context/merchant-api.ts
index a531a5958..23ea05cd2 100644
--- a/packages/web-util/src/context/merchant-api.ts
+++ b/packages/web-util/src/context/merchant-api.ts
@@ -79,6 +79,9 @@ type Evictors = {
 type ConfigResult<T> =
   | undefined
   | { type: "ok"; config: T; hints: VersionHint[] }
+  | ConfigResultFail<T>;
+
+export type ConfigResultFail<T> =
   | { type: "incompatible"; result: T; supported: string }
   | { type: "error"; error: TalerError };
 
@@ -91,7 +94,7 @@ export const MerchantApiProvider = ({
   baseUrl: URL;
   evictors?: Evictors;
   children: ComponentChildren;
-  frameOnError: FunctionComponent<{ children: ComponentChildren }>;
+  frameOnError: FunctionComponent<{ state: 
ConfigResultFail<TalerMerchantApi.VersionResponse> | undefined }>;
 }): VNode => {
   const [checked, setChecked] =
     useState<ConfigResult<TalerMerchantApi.VersionResponse>>();
@@ -120,24 +123,8 @@ export const MerchantApiProvider = ({
       });
   }, []);
 
-  if (checked === undefined) {
-    return h(frameOnError, {
-      children: h("div", {}, "checking compatibility with server..."),
-    });
-  }
-  if (checked.type === "error") {
-    return h(frameOnError, {
-      children: h(ErrorLoading, { error: checked.error, showDetail: true }),
-    });
-  }
-  if (checked.type === "incompatible") {
-    return h(frameOnError, {
-      children: h(
-        "div",
-        {},
-        i18n.str`The server version is not supported. Supported version 
"${checked.supported}", server version "${checked.result.version}"`,
-      ),
-    });
+  if (!checked || checked.type !== "ok") {
+    return h(frameOnError, { state: checked }, []);
   }
 
   const value: MerchantContextType = {
diff --git a/packages/web-util/src/utils/request.ts 
b/packages/web-util/src/utils/request.ts
index f8a892d99..70f943540 100644
--- a/packages/web-util/src/utils/request.ts
+++ b/packages/web-util/src/utils/request.ts
@@ -41,7 +41,7 @@ export async function defaultRequestHandler<T>(
 ): Promise<HttpResponseOk<T>> {
   const requestHeaders: Record<string, string> = {};
   if (options.token) {
-    requestHeaders.Authorization = `Bearer ${options.token}`;
+    requestHeaders.Authorization = `Bearer secret-token:${options.token}`;
   } else if (options.basicAuth) {
     requestHeaders.Authorization = `Basic ${base64encode(
       `${options.basicAuth.username}:${options.basicAuth.password}`,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]