gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 02/02: fix new libeufin api


From: gnunet
Subject: [taler-wallet-core] 02/02: fix new libeufin api
Date: Mon, 13 Nov 2023 19:34:03 +0100

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

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

commit ca076e5eab10d2d471dd68732a7d8a7ac9f5f6bc
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon Nov 13 15:33:13 2023 -0300

    fix new libeufin api
---
 packages/demobank-ui/src/hooks/circuit.ts          |  30 ++--
 .../demobank-ui/src/pages/ShowAccountDetails.tsx   |   2 +-
 packages/demobank-ui/src/pages/admin/AdminHome.tsx |  14 +-
 .../src/pages/business/CreateCashout.tsx           |  52 +++---
 .../src/pages/business/ShowCashoutDetails.tsx      |  30 +++-
 packages/demobank-ui/src/utils.ts                  |   1 -
 .../taler-harness/src/http-client/bank-core.ts     |  21 ++-
 packages/taler-util/src/http-client/bank-core.ts   |  89 ++++++++--
 packages/taler-util/src/http-client/types.ts       | 185 +++++++++++++--------
 9 files changed, 275 insertions(+), 149 deletions(-)

diff --git a/packages/demobank-ui/src/hooks/circuit.ts 
b/packages/demobank-ui/src/hooks/circuit.ts
index 845f37822..44edb4f8a 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -266,26 +266,34 @@ export function useLastMonitorInfo(time: Date, timeframe: 
TalerCorebankApi.Monit
     const current: TalerCoreBankResultByMethod<"getMonitor"> = {
       type: "ok" as const,
       body: {
-        type: "with-cashout" as const,
+        type: "with-conversions" as const,
         cashinCount: 1,
-        cashinExternalVolume: "LOCAL:1234" as AmountString,
+        cashinFiatVolume: "LOCAL:2345" as AmountString,
+        cashinRegionalVolume: "LOCAL:2345" as AmountString,
         cashoutCount: 2,
-        cashoutExternalVolume: "LOCAL:2345" as AmountString,
-        talerPayoutCount: 3,
-        talerPayoutInternalVolume: "LOCAL:3456" as AmountString,
+        cashoutFiatVolume: "LOCAL:2345" as AmountString,
+        cashoutRegionalVolume: "LOCAL:2345" as AmountString,
+        talerInCount: 1,
+        talerInVolume: "LOCAL:2345" as AmountString,
+        talerOutCount: 2,
+        talerOutVolume: "LOCAL:2345" as AmountString,
       }
     }
 
-    const previous = {
+    const previous: TalerCoreBankResultByMethod<"getMonitor">  = {
       type: "ok" as const,
       body: {
-        type: "with-cashout" as const,
+        type: "with-conversions" as const,
         cashinCount: 1,
-        cashinExternalVolume: "LOCAL:2345" as AmountString,
+        cashinFiatVolume: "LOCAL:2345" as AmountString,
+        cashinRegionalVolume: "LOCAL:2345" as AmountString,
         cashoutCount: 2,
-        cashoutExternalVolume: "LOCAL:2345" as AmountString,
-        talerPayoutCount: 3,
-        talerPayoutInternalVolume: "LOCAL:3456" as AmountString,
+        cashoutFiatVolume: "LOCAL:2345" as AmountString,
+        cashoutRegionalVolume: "LOCAL:2345" as AmountString,
+        talerInCount: 1,
+        talerInVolume: "LOCAL:2345" as AmountString,
+        talerOutCount: 2,
+        talerOutVolume: "LOCAL:2345" as AmountString,
       }
 
     }
diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx 
b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
index 2e00fdbba..a88a90499 100644
--- a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
@@ -58,7 +58,7 @@ export function ShowAccountDetails({
           email: submitAccount.contact_data?.email,
           phone: submitAccount.contact_data?.phone,
         }),
-        is_exchange: false,
+        is_taler_exchange: false,
         name: submitAccount.name,
       });
 
diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx 
b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
index 9bc2ee571..a89b4afca 100644
--- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
@@ -124,15 +124,15 @@ function Metrics(): VNode {
     </div>
     <dl class="mt-5 grid grid-cols-1 divide-y divide-gray-200 overflow-hidden 
rounded-lg bg-white shadow-lg md:grid-cols-3 md:divide-x md:divide-y-0">
 
-      {resp.current.body.type !== "with-cashout" || resp.previous.body.type 
!== "with-cashout" ? undefined :
+      {resp.current.body.type !== "with-conversions" || 
resp.previous.body.type !== "with-conversions" ? undefined :
         <Fragment>
           <div class="px-4 py-5 sm:p-6">
             <dt class="text-base font-normal text-gray-900">
               <i18n.Translate>Cashin</i18n.Translate>
             </dt>
             <MetricValue
-              current={resp.current.body.cashinExternalVolume}
-              previous={resp.previous.body.cashinExternalVolume}
+              current={resp.current.body.cashinFiatVolume}
+              previous={resp.previous.body.cashinFiatVolume}
             />
           </div>
           <div class="px-4 py-5 sm:p-6">
@@ -140,8 +140,8 @@ function Metrics(): VNode {
               <i18n.Translate>Cashout</i18n.Translate>
             </dt>
             <MetricValue
-              current={resp.current.body.cashoutExternalVolume}
-              previous={resp.previous.body.cashoutExternalVolume}
+              current={resp.current.body.cashoutFiatVolume}
+              previous={resp.previous.body.cashoutFiatVolume}
             />
           </div>
         </Fragment>
@@ -151,8 +151,8 @@ function Metrics(): VNode {
           <i18n.Translate>Payout</i18n.Translate>
         </dt>
         <MetricValue
-          current={resp.current.body.talerPayoutInternalVolume}
-          previous={resp.previous.body.talerPayoutInternalVolume}
+          current={resp.current.body.talerOutVolume}
+          previous={resp.previous.body.talerOutVolume}
         />
       </div>
     </dl>
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx 
b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 10be5ec11..525a170bc 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -16,19 +16,22 @@
 import {
   Amounts,
   TalerError,
-  TranslatedString
+  TranslatedString,
+  encodeCrock,
+  getRandomBytes
 } from "@gnu-taler/taler-util";
 import {
+  Attention,
+  ErrorLoading,
+  Loading,
+  LocalNotificationBanner,
+  ShowInputErrorLabel,
   useLocalNotification,
   useTranslationContext
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { mutate } from "swr";
-import { Attention } from "@gnu-taler/web-util/browser";
-import { ErrorLoading } from "@gnu-taler/web-util/browser";
-import { Loading } from "@gnu-taler/web-util/browser";
-import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
 import { useBankCoreApiContext } from "../../context/config.js";
 import { useAccountDetails } from "../../hooks/access.js";
 import { useBackendState } from "../../hooks/backend.js";
@@ -37,13 +40,11 @@ import {
 } from "../../hooks/circuit.js";
 import {
   TanChannel,
-  undefinedIfEmpty,
-  withRuntimeErrorHandling
+  undefinedIfEmpty
 } from "../../utils.js";
 import { LoginForm } from "../LoginForm.js";
 import { InputAmount } from "../PaytoWireTransferForm.js";
 import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { LocalNotificationBanner } from "@gnu-taler/web-util/browser";
 
 interface Props {
   account: string;
@@ -321,21 +322,6 @@ export function CreateCashout({
                 updateForm(structuredClone(form));
               }}
             />
-            <input
-              class={
-                "pure-button content " +
-                (form.channel === TanChannel.FILE
-                  ? "pure-button-primary"
-                  : "pure-button-secondary")
-              }
-              type="submit"
-              value={i18n.str`FILE`}
-              onClick={async (e) => {
-                e.preventDefault();
-                form.channel = TanChannel.FILE;
-                updateForm(structuredClone(form));
-              }}
-            />
           </div>
           <ShowInputErrorLabel
             message={errors?.channel}
@@ -363,7 +349,9 @@ export function CreateCashout({
 
               if (errors || !creds) return;
               await handleError(async () => {
+                const request_uid = encodeCrock(getRandomBytes(16))
                 const resp = await api.createCashout(creds, {
+                  request_uid,
                   amount_credit: Amounts.stringify(calc.credit),
                   amount_debit: Amounts.stringify(calc.debit),
                   subject: form.subject,
@@ -404,12 +392,18 @@ export function CreateCashout({
                       description: resp.detail.hint as TranslatedString,
                       debug: resp.detail,
                     });
-                    // case "": return notify({
-                    //   type: "error",
-                    //   title: i18n.str`This user is not allowed to make a 
cashout`,
-                    //   description: resp.detail.hint as TranslatedString,
-                    //   debug: resp.detail,
-                    // });
+                    case "request-already-used": return notify({
+                      type: "error",
+                      title: i18n.str`Duplicated request found, try again.`,
+                      description: resp.detail.hint as TranslatedString,
+                      debug: resp.detail,
+                    });
+                    case "tan-failed": return notify({
+                      type: "error",
+                      title: i18n.str`Server couldn't send the confirmation 
request.`,
+                      description: resp.detail.hint as TranslatedString,
+                      debug: resp.detail,
+                    });
                     default: assertUnreachable(resp)
                   }
                 }
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx 
b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
index 4646e9220..ddfc18a0c 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
@@ -121,12 +121,12 @@ export function ShowCashoutDetails({
           </label>
           <input readOnly value={result.body.status} />
         </fieldset>
-        <fieldset>
+        {/* <fieldset>
           <label>
             <i18n.Translate>Destination</i18n.Translate>
           </label>
           <input readOnly value={result.body.credit_payto_uri} />
-        </fieldset>
+        </fieldset> */}
         {isPending ? (
           <fieldset>
             <label>
@@ -220,15 +220,33 @@ export function ShowCashoutDetails({
                         description: resp.detail.hint as TranslatedString,
                         debug: resp.detail,
                       })
-                      case "wrong-tan-or-credential": return notify({
+                      case "no-enough-balance": return notify({
+                        type: "error",
+                        title: i18n.str`The account does not have sufficient 
funds`,
+                        description: resp.detail.hint as TranslatedString,
+                        debug: resp.detail,
+                      });
+                      case "incorrect-exchange-rate": return notify({
+                        type: "error",
+                        title: i18n.str`The exchange rate was incorrectly 
applied`,
+                        description: resp.detail.hint as TranslatedString,
+                        debug: resp.detail,
+                      });
+                      case "already-aborted": return notify({
+                        type: "error",
+                        title: i18n.str`The cashout operation is already 
aborted.`,
+                        description: resp.detail.hint as TranslatedString,
+                        debug: resp.detail,
+                      });
+                      case "no-cashout-payto": return notify({
                         type: "error",
-                        title: i18n.str`Invalid code or credentials.`,
+                        title: i18n.str`Missing destination account.`,
                         description: resp.detail.hint as TranslatedString,
                         debug: resp.detail,
                       })
-                      case "cashout-address-changed": return notify({
+                      case "too-many-attempts": return notify({
                         type: "error",
-                        title: i18n.str`The cash-out address between the 
creation and the confirmation changed.`,
+                        title: i18n.str`Too many failed attempts.`,
                         description: resp.detail.hint as TranslatedString,
                         debug: resp.detail,
                       })
diff --git a/packages/demobank-ui/src/utils.ts 
b/packages/demobank-ui/src/utils.ts
index 437618150..18abf28a9 100644
--- a/packages/demobank-ui/src/utils.ts
+++ b/packages/demobank-ui/src/utils.ts
@@ -78,7 +78,6 @@ export type RecursivePartial<T> = {
 export enum TanChannel {
   SMS = "sms",
   EMAIL = "email",
-  FILE = "file",
 }
 export enum CashoutStatus {
   // The payment was initiated after a valid
diff --git a/packages/taler-harness/src/http-client/bank-core.ts 
b/packages/taler-harness/src/http-client/bank-core.ts
index 9919fc0a7..22a10580d 100644
--- a/packages/taler-harness/src/http-client/bank-core.ts
+++ b/packages/taler-harness/src/http-client/bank-core.ts
@@ -16,13 +16,18 @@ export function createTestForBankCore(api: 
TalerCoreBankHttpClient, adminToken:
       "no-contact-info": undefined,
       "no-enough-balance": undefined,
       "cashout-not-supported": undefined,
+      "request-already-used": undefined,
+      "tan-failed": undefined,
       success: undefined,
     },
     test_confirmCashoutById: {
-      "cashout-address-changed": undefined,
+      "already-aborted": undefined,
+      "incorrect-exchange-rate": undefined,
+      "no-cashout-payto": undefined,
+      "no-enough-balance": undefined,
+      "too-many-attempts": undefined,
       "cashout-not-supported": undefined,
       "not-found": undefined,
-      "wrong-tan-or-credential": undefined,
       success: undefined,
     },
     test_getAccountCashouts: {
@@ -37,8 +42,18 @@ export function createTestForBankCore(api: 
TalerCoreBankHttpClient, adminToken:
     },
     test_getCashoutRate: {
       "cashout-not-supported": undefined,
-      "not-supported": undefined,
       "wrong-calculation": undefined,
+      "amount-too-small": undefined,
+      "missing-params": undefined,
+      "wrong-currency": undefined,
+      success: undefined,
+    },
+    test_getCashinRate: {
+      "cashout-not-supported": undefined,
+      "wrong-calculation": undefined,
+      "amount-too-small": undefined,
+      "missing-params": undefined,
+      "wrong-currency": undefined,
       success: undefined,
     },
     test_getGlobalCashouts: {
diff --git a/packages/taler-util/src/http-client/bank-core.ts 
b/packages/taler-util/src/http-client/bank-core.ts
index 1107a3c93..0b99943a3 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -31,7 +31,7 @@ import { TalerAuthenticationHttpClient } from 
"./authentication.js";
 import { TalerBankIntegrationHttpClient } from "./bank-integration.js";
 import { TalerRevenueHttpClient } from "./bank-revenue.js";
 import { TalerWireGatewayHttpClient } from "./bank-wire.js";
-import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, 
codecForAccountData, codecForBankAccountCreateWithdrawalResponse, 
codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, 
codecForBankAccountTransactionsResponse, codecForCashoutConversionResponse, 
codecForCashoutPending, codecForCashoutStatusResponse, codecForCashouts, 
codecForCoreBankConfig, codecForGlobalCashouts, 
codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccoun 
[...]
+import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, 
codecForAccountData, codecForBankAccountCreateWithdrawalResponse, 
codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, 
codecForBankAccountTransactionsResponse, codecForCashinConversionResponse, 
codecForCashoutConversionResponse, codecForCashoutPending, 
codecForCashoutStatusResponse, codecForCashouts, codecForCoreBankConfig, 
codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMon [...]
 import { addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js";
 
 
@@ -181,6 +181,9 @@ export class TalerCoreBankHttpClient {
       case HttpStatusCode.NoContent: return opEmptySuccess()
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
       case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
+      //FIXME: add code to split cases
+      // * An admin account tried to make its account an exchange
+      // * A non-admin user tried to change properties reserved for the admin
       case HttpStatusCode.Forbidden: return 
opKnownFailure("old-password-invalid-or-not-allowed", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
@@ -444,13 +447,15 @@ export class TalerCoreBankHttpClient {
         const body = await resp.json()
         const details = codecForTalerErrorDetail().decode(body)
         switch (details.code) {
+          case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return 
opKnownFailure("request-already-used", resp);
           case TalerErrorCode.BANK_BAD_CONVERSION: return 
opKnownFailure("incorrect-exchange-rate", resp);
           case TalerErrorCode.BANK_MISSING_TAN_INFO: return 
opKnownFailure("no-contact-info", resp);
           case TalerErrorCode.BANK_UNALLOWED_DEBIT: return 
opKnownFailure("no-enough-balance", resp);
           default: return opUnknownFailure(resp, body)
         }
       }
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.BadGateway: return opKnownFailure("tan-failed", 
resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -472,7 +477,7 @@ export class TalerCoreBankHttpClient {
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
       case HttpStatusCode.Conflict: return opKnownFailure("already-confirmed", 
resp);
       //FIXME: should be 404 ?
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -492,11 +497,22 @@ export class TalerCoreBankHttpClient {
     });
     switch (resp.status) {
       case HttpStatusCode.NoContent: return opEmptySuccess()
-      case HttpStatusCode.Forbidden: return 
opKnownFailure("wrong-tan-or-credential", resp);
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
-      case HttpStatusCode.Conflict: return 
opKnownFailure("cashout-address-changed", resp);
-      //FIXME: should be 404 ?
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      // case HttpStatusCode.Forbidden: return 
opKnownFailure("wrong-tan-or-credential", resp);
+      case HttpStatusCode.Conflict: {
+        const body = await resp.json()
+        const details = codecForTalerErrorDetail().decode(body)
+        switch (details.code) {
+          case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return 
opKnownFailure("already-aborted", resp);
+          case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return 
opKnownFailure("no-cashout-payto", resp);
+          case TalerErrorCode.BANK_UNALLOWED_DEBIT: return 
opKnownFailure("no-enough-balance", resp);
+          case TalerErrorCode.BANK_BAD_CONVERSION: return 
opKnownFailure("incorrect-exchange-rate", resp);
+          // case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return 
opKnownFailure("no-enough-balance", resp);
+          default: return opUnknownFailure(resp, body)
+        }
+      }
+      case HttpStatusCode.TooManyRequests: return 
opKnownFailure("too-many-attempts", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -518,7 +534,7 @@ export class TalerCoreBankHttpClient {
       case HttpStatusCode.Ok: return opSuccess(resp, codecForCashouts())
       case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
       case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", 
resp);;
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -538,7 +554,7 @@ export class TalerCoreBankHttpClient {
     switch (resp.status) {
       case HttpStatusCode.Ok: return opSuccess(resp, 
codecForCashoutStatusResponse())
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -559,7 +575,7 @@ export class TalerCoreBankHttpClient {
     switch (resp.status) {
       case HttpStatusCode.Ok: return opSuccess(resp, codecForGlobalCashouts())
       case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
@@ -574,24 +590,61 @@ export class TalerCoreBankHttpClient {
       url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit))
     }
     if (conversion.credit) {
-      url.searchParams.set("amount_debit", 
Amounts.stringify(conversion.credit))
+      url.searchParams.set("amount_credit", 
Amounts.stringify(conversion.credit))
     }
     const resp = await this.httpLib.fetch(url.href, {
       method: "GET",
     });
     switch (resp.status) {
       case HttpStatusCode.Ok: return opSuccess(resp, 
codecForCashoutConversionResponse())
-      // FIXME: error code for
-      // * the requested currency was not supported
-      // * the calculation is not correct
-      case HttpStatusCode.BadRequest: return 
opKnownFailure("wrong-calculation", resp);
-      case HttpStatusCode.NotFound: return opKnownFailure("not-supported", 
resp);
-      //FIXME: should be 404 ?
-      case HttpStatusCode.ServiceUnavailable: return 
opKnownFailure("cashout-not-supported", resp);
+      case HttpStatusCode.BadRequest: {
+        const body = await resp.json()
+        const details = codecForTalerErrorDetail().decode(body)
+        switch (details.code) {
+          case TalerErrorCode.GENERIC_PARAMETER_MISSING: return 
opKnownFailure("missing-params", resp);
+          case TalerErrorCode.GENERIC_PARAMETER_MALFORMED : return 
opKnownFailure("wrong-calculation", resp);
+          case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return 
opKnownFailure("wrong-currency", resp);
+          default: return opUnknownFailure(resp, body)
+        }
+      }
+      case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", 
resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
 
+  /**
+   * https://docs.taler.net/core/api-corebank.html#get--cashin-rate
+   * 
+   */
+  async getCashinRate(conversion: { debit?: AmountJson, credit?: AmountJson }) 
{
+    const url = new URL(`cashin-rate`, this.baseUrl);
+    if (conversion.debit) {
+      url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit))
+    }
+    if (conversion.credit) {
+      url.searchParams.set("amount_credit", 
Amounts.stringify(conversion.credit))
+    }
+    const resp = await this.httpLib.fetch(url.href, {
+      method: "GET",
+    });
+    switch (resp.status) {
+      case HttpStatusCode.Ok: return opSuccess(resp, 
codecForCashinConversionResponse())
+      case HttpStatusCode.BadRequest: {
+        const body = await resp.json()
+        const details = codecForTalerErrorDetail().decode(body)
+        switch (details.code) {
+          case TalerErrorCode.GENERIC_PARAMETER_MISSING: return 
opKnownFailure("missing-params", resp);
+          case TalerErrorCode.GENERIC_PARAMETER_MALFORMED : return 
opKnownFailure("wrong-calculation", resp);
+          case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return 
opKnownFailure("wrong-currency", resp);
+          default: return opUnknownFailure(resp, body)
+        }
+      }
+      case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", 
resp);
+      case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
+      default: return opUnknownFailure(resp, await resp.text())
+    }
+  }
   //
   // MONITOR
   //
diff --git a/packages/taler-util/src/http-client/types.ts 
b/packages/taler-util/src/http-client/types.ts
index 77004cf5b..f6542abcd 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -357,13 +357,13 @@ export const codecForBankAccountTransactionsResponse =
 export const codecForBankAccountTransactionInfo =
   (): Codec<TalerCorebankApi.BankAccountTransactionInfo> =>
     buildCodecForObject<TalerCorebankApi.BankAccountTransactionInfo>()
-      .property("amount", codecForAmountString())
       .property("creditor_payto_uri", codecForPaytoString())
-      .property("date", codecForTimestamp)
       .property("debtor_payto_uri", codecForPaytoString())
+      .property("amount", codecForAmountString())
       .property("direction", codecForEither(codecForConstString("debit"), 
codecForConstString("credit")))
-      .property("row_id", codecForNumber())
       .property("subject", codecForString())
+      .property("row_id", codecForNumber())
+      .property("date", codecForTimestamp)
       .build("TalerCorebankApi.BankAccountTransactionInfo");
 
 export const codecForBankAccountCreateWithdrawalResponse =
@@ -376,8 +376,8 @@ export const codecForBankAccountCreateWithdrawalResponse =
 export const codecForBankAccountGetWithdrawalResponse =
   (): Codec<TalerCorebankApi.BankAccountGetWithdrawalResponse> =>
     buildCodecForObject<TalerCorebankApi.BankAccountGetWithdrawalResponse>()
-      .property("aborted", codecForBoolean())
       .property("amount", codecForAmountString())
+      .property("aborted", codecForBoolean())
       .property("confirmation_done", codecForBoolean())
       .property("selected_exchange_account", 
codecOptional(codecForPaytoString()))
       .property("selected_reserve_pub", codecOptional(codecForString()))
@@ -397,6 +397,13 @@ export const codecForCashoutConversionResponse =
       .property("amount_debit", codecForAmountString())
       .build("TalerCorebankApi.CashoutConversionResponse");
 
+export const codecForCashinConversionResponse =
+  (): Codec<TalerCorebankApi.CashinConversionResponse> =>
+    buildCodecForObject<TalerCorebankApi.CashinConversionResponse>()
+      .property("amount_credit", codecForAmountString())
+      .property("amount_debit", codecForAmountString())
+      .build("TalerCorebankApi.CashinConversionResponse");
+
 export const codecForCashouts =
   (): Codec<TalerCorebankApi.Cashouts> =>
     buildCodecForObject<TalerCorebankApi.Cashouts>()
@@ -407,7 +414,7 @@ export const codecForCashoutInfo =
   (): Codec<TalerCorebankApi.CashoutInfo> =>
     buildCodecForObject<TalerCorebankApi.CashoutInfo>()
       .property("cashout_id", codecForString())
-      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("confirmed"),))
+      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("aborted"), codecForConstString("confirmed"),))
       .build("TalerCorebankApi.CashoutInfo");
 
 export const codecForGlobalCashouts =
@@ -421,7 +428,7 @@ export const codecForGlobalCashoutInfo =
     buildCodecForObject<TalerCorebankApi.GlobalCashoutInfo>()
       .property("cashout_id", codecForString())
       .property("username", codecForString())
-      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("confirmed"),))
+      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("aborted"), codecForConstString("confirmed"),))
       .build("TalerCorebankApi.GlobalCashoutInfo");
 
 export const codecForCashoutStatusResponse =
@@ -431,8 +438,8 @@ export const codecForCashoutStatusResponse =
       .property("amount_debit", codecForAmountString())
       .property("confirmation_time", codecForTimestamp)
       .property("creation_time", codecForTimestamp)
-      .property("credit_payto_uri", codecForPaytoString())
-      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("confirmed")))
+      // .property("credit_payto_uri", codecForPaytoString())
+      .property("status", codecForEither(codecForConstString("pending"), 
codecForConstString("aborted"), codecForConstString("confirmed")))
       .property("subject", codecForString())
       .build("TalerCorebankApi.CashoutStatusResponse");
 
@@ -448,28 +455,34 @@ export const codecForConversionRatesResponse =
 
 export const codecForMonitorResponse = (): 
Codec<TalerCorebankApi.MonitorResponse> => 
buildCodecForUnion<TalerCorebankApi.MonitorResponse>()
   .discriminateOn("type")
-  .alternative("just-payouts", codecForMonitorResponseJustPayout())
-  .alternative("with-cashout", codecForMonitorResponseWithCashout())
+  .alternative("no-conversions", codecForMonitorNoConversion())
+  .alternative("with-conversions", codecForMonitorWithCashout())
   .build("TalerWireGatewayApi.IncomingBankTransaction");
 
-export const codecForMonitorResponseJustPayout =
-  (): Codec<TalerCorebankApi.MonitorJustPayouts> =>
-    buildCodecForObject<TalerCorebankApi.MonitorJustPayouts>()
-      .property("type", codecForConstString("just-payouts"))
-      .property("talerPayoutCount", codecForNumber())
-      .property("talerPayoutInternalVolume", codecForAmountString())
+export const codecForMonitorNoConversion =
+  (): Codec<TalerCorebankApi.MonitorNoConversion> =>
+    buildCodecForObject<TalerCorebankApi.MonitorNoConversion>()
+      .property("type", codecForConstString("no-conversions"))
+      .property("talerInCount", codecForNumber())
+      .property("talerInVolume", codecForAmountString())
+      .property("talerOutCount", codecForNumber())
+      .property("talerOutVolume", codecForAmountString())
       .build("TalerCorebankApi.MonitorJustPayouts");
 
-export const codecForMonitorResponseWithCashout =
-  (): Codec<TalerCorebankApi.MonitorWithCashout> =>
-    buildCodecForObject<TalerCorebankApi.MonitorWithCashout>()
-      .property("type", codecForConstString("with-cashout"))
-      .property("cashinCount", (codecForNumber()))
-      .property("cashinExternalVolume", (codecForAmountString()))
-      .property("cashoutCount", (codecForNumber()))
-      .property("cashoutExternalVolume", (codecForAmountString()))
-      .property("talerPayoutCount", codecForNumber())
-      .property("talerPayoutInternalVolume", codecForAmountString())
+export const codecForMonitorWithCashout =
+  (): Codec<TalerCorebankApi.MonitorWithConversion> =>
+    buildCodecForObject<TalerCorebankApi.MonitorWithConversion>()
+      .property("type", codecForConstString("with-conversions"))
+      .property("cashinCount", codecForNumber())
+      .property("cashinFiatVolume", codecForAmountString())
+      .property("cashinRegionalVolume", codecForAmountString())
+      .property("cashoutCount", codecForNumber())
+      .property("cashoutFiatVolume", codecForAmountString())
+      .property("cashoutRegionalVolume", codecForAmountString())
+      .property("talerInCount", codecForNumber())
+      .property("talerInVolume", codecForAmountString())
+      .property("talerOutCount", codecForNumber())
+      .property("talerOutVolume", codecForAmountString())
       .build("TalerCorebankApi.MonitorWithCashout");
 
 export const codecForBankVersion =
@@ -697,7 +710,6 @@ const codecForDecimalNumber = codecForNumber
 enum TanChannel {
   SMS = "sms",
   EMAIL = "email",
-  FILE = "file"
 }
 
 export namespace TalerWireGatewayApi {
@@ -1174,7 +1186,7 @@ export namespace TalerCorebankApi {
 
     // If present, change the is_exchange configuration.
     // See RegisterAccountRequest
-    is_exchange?: boolean;
+    is_taler_exchange?: boolean;
 
     // If present, change the max debit allowed for this user
     // Only admin can change this property.
@@ -1252,10 +1264,15 @@ export namespace TalerCorebankApi {
 
   export interface CashoutRequest {
 
+    // Nonce to make the request idempotent.  Requests with the same
+    // request_uid that differ in any of the other fields
+    // are rejected.
+    request_uid: ShortHashCode;
+
     // Optional subject to associate to the
     // cashout operation.  This data will appear
     // as the incoming wire transfer subject in
-    // the user's external bank account.
+    // the user's fiat bank account.
     subject?: string;
 
     // That is the plain amount that the user specified
@@ -1301,6 +1318,15 @@ export namespace TalerCorebankApi {
     amount_credit: AmountString;
   }
 
+  export interface CashinConversionResponse {
+    // Amount that the user will get deducted from their fiat
+    // bank account, according to the 'amount_credit' value.
+    amount_debit: AmountString;
+    // Amount that the user will receive in their regional
+    // bank account, according to 'amount_debit'.
+    amount_credit: AmountString;
+  }
+
   export interface Cashouts {
     // Every string represents a cash-out operation ID.
     cashouts: CashoutInfo[];
@@ -1308,7 +1334,7 @@ export namespace TalerCorebankApi {
 
   export interface CashoutInfo {
     cashout_id: string;
-    status: "pending" | "confirmed";
+    status: "pending" | "aborted" | "confirmed";
   }
   export interface GlobalCashouts {
     // Every string represents a cash-out operation ID.
@@ -1317,11 +1343,11 @@ export namespace TalerCorebankApi {
   export interface GlobalCashoutInfo {
     cashout_id: string;
     username: string;
-    status: "pending" | "confirmed";
+    status: "pending" | "aborted" | "confirmed";
   }
 
   export interface CashoutStatusResponse {
-    status: "pending" | "confirmed";
+    status: "pending" | "aborted" | "confirmed";
 
     // Amount debited to the internal
     // regional currency bank account.
@@ -1335,7 +1361,7 @@ export namespace TalerCorebankApi {
 
     // Fiat bank account that will receive the cashed out amount.
     // Specified as a payto URI.
-    credit_payto_uri: PaytoString;
+    // credit_payto_uri: PaytoString;
 
     // Time when the cashout was created.
     creation_time: Timestamp;
@@ -1365,59 +1391,72 @@ export namespace TalerCorebankApi {
   }
 
   export type MonitorResponse =
-    | MonitorJustPayouts
-    | MonitorWithCashout;
+    | MonitorNoConversion
+    | MonitorWithConversion;
 
   // Monitoring stats when conversion is not supported
-  export interface MonitorJustPayouts {
-    type: "just-payouts";
+  export interface MonitorNoConversion {
+    type: "no-conversions";
+
+    // How many payments were made to a Taler exchange by another
+    // bank account.
+    talerInCount: number;
 
-    // This number identifies how many payments were made by a
-    // Taler exchange to a merchant bank account in the internal
-    // currency, in the timeframe specified in the request.
-    talerPayoutCount: number;
+    // Overall volume that has been paid to a Taler
+    // exchange by another bank account.
+    talerInVolume: AmountString;
 
-    // This amount accounts the overall *internal* currency that
-    // has been paid by a Taler exchange to a merchant internal
-    // bank account, in the timeframe specified in the request.
-    talerPayoutInternalVolume: AmountString;
+    // How many payments were made by a Taler exchange to another
+    // bank account.
+    talerOutCount: number;
+
+    // Overall volume that has been paid by a Taler
+    // exchange to another bank account.
+    talerOutVolume: AmountString;
   }
   // Monitoring stats when conversion is supported
-  export interface MonitorWithCashout {
-    type: "with-cashout";
+  export interface MonitorWithConversion {
+    type: "with-conversions";
 
-    // This number identifies how many cashin operations
-    // took place in the timeframe specified in the request.
-    // This number corresponds to how many withdrawals have
-    // been initiated by a wallet owner.  Note: wallet owners
+    // How many cashin operations were confirmed by a
+    // wallet owner. Note: wallet owners
     // are NOT required to be customers of the libeufin-bank.
     cashinCount: number;
 
-    // This amount accounts how much external currency has been
-    // spent to withdraw Taler coins in the internal currency.
-    // The exact amount of internal currency being created can be
-    // calculated using the advertised conversion rates.
-    cashinExternalVolume: AmountString;
+    // Overall regional currency that has been paid by the regional admin 
account
+    // to regional bank accounts to fulfill all the confirmed cashin 
operations.
+    cashinRegionalVolume: AmountString;
+
+    // Overall fiat currency that has been paid to the fiat admin account
+    // by fiat bank accounts to fulfill all the confirmed cashin operations.
+    cashinFiatVolume: AmountString;
 
-    // This number identifies how many cashout operations were
-    // confirmed in the timeframe speficied in the request.
+    // How many cashout operations were confirmed.
     cashoutCount: number;
 
-    // This amount corresponds to how much *external* currency was
-    // paid by the libeufin-bank administrator to fulfill all the
-    // confirmed cashouts related to the timeframe specified in the
-    // request.
-    cashoutExternalVolume: AmountString;
-
-    // This number identifies how many payments were made by a
-    // Taler exchange to a merchant bank account in the internal
-    // currency, in the timeframe specified in the request.
-    talerPayoutCount: number;
-
-    // This amount accounts the overall *internal* currency that
-    // has been paid by a Taler exchange to a merchant internal
-    // bank account, in the timeframe specified in the request.
-    talerPayoutInternalVolume: AmountString;
+    // Overall regional currency that has been paid to the regional admin 
account
+    // by fiat bank accounts to fulfill all the confirmed cashout operations.
+    cashoutRegionalVolume: AmountString;
+
+    // Overall fiat currency that has been paid by the fiat admin account
+    // to fiat bank accounts to fulfill all the confirmed cashout operations.
+    cashoutFiatVolume: AmountString;
+
+    // How many payments were made to a Taler exchange by another
+    // bank account.
+    talerInCount: number;
+
+    // Overall volume that has been paid to a Taler
+    // exchange by another bank account.
+    talerInVolume: AmountString;
+
+    // How many payments were made by a Taler exchange to another
+    // bank account.
+    talerOutCount: number;
+
+    // Overall volume that has been paid by a Taler
+    // exchange to another bank account.
+    talerOutVolume: AmountString;
   }
 
 

-- 
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]