gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: update to exchange v21 and me


From: gnunet
Subject: [taler-wallet-core] branch master updated: update to exchange v21 and merchant v17
Date: Fri, 06 Sep 2024 18:15:09 +0200

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 d671ef0f4 update to exchange v21 and merchant v17
d671ef0f4 is described below

commit d671ef0f4cfa7d17b43b265501ae595882549f17
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Sep 6 13:08:26 2024 -0300

    update to exchange v21 and merchant v17
---
 .../aml-backoffice-ui/src/pages/CaseDetails.tsx    |   2 +-
 .../aml-backoffice-ui/src/pages/CaseUpdate.tsx     |   2 +-
 .../paths/instance/kyc/list/ListPage.stories.tsx   |   6 +-
 .../src/paths/instance/kyc/list/ListPage.tsx       |  17 +---
 .../src/paths/instance/orders/create/index.tsx     |  39 ++++++--
 .../src/paths/instance/orders/details/index.tsx    |  30 +++++-
 .../src/paths/instance/orders/list/index.tsx       |  32 ++++++-
 .../src/paths/instance/templates/use/index.tsx     |  39 ++++++--
 packages/taler-harness/src/harness/helpers.ts      |   2 +-
 packages/taler-util/src/http-client/exchange.ts    |  16 ++--
 packages/taler-util/src/http-client/merchant.ts    |  11 ++-
 packages/taler-util/src/taler-signatures.ts        |   4 +-
 packages/taler-util/src/types-taler-exchange.ts    | 104 ++++++++++++++++-----
 packages/taler-util/src/types-taler-merchant.ts    |  68 +++++++++++++-
 14 files changed, 290 insertions(+), 82 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx 
b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
index cf6922e1a..54f979846 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
@@ -355,7 +355,7 @@ export function CaseDetails({ account }: { account: string 
}) {
               justification: "",
               keep_investigating: false,
               properties: {},
-              new_measure: "m2",
+              new_measures: "m2",
               new_rules: {
                 custom_measures: {},
                 expiration_time: AbsoluteTime.toProtocolTimestamp(
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx 
b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
index b79746107..2708dba4c 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
@@ -174,7 +174,7 @@ export function CaseUpdate({
                 successor_measure: undefined,
               },
               properties: {},
-              new_measure: undefined,
+              new_measures: undefined,
             };
 
             return api.makeAmlDesicion(officer.account, decision);
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
 
b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
index 046636b4b..44fa429a4 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
@@ -37,18 +37,18 @@ export const Example = tests.createExample(TestedComponent, 
{
     timeout_kycs: [],
     pending_kycs: [
       {
-        aml_status: 0,
         exchange_url: "http://exchange.taler";,
         payto_uri: "payto://iban/de123123123" as PaytoString,
         kyc_url: "http://exchange.taler/kyc";,
+        exchange_http_status: 0,
       },
       {
-        aml_status: 1,
+        exchange_http_status: 1,
         exchange_url: "http://exchange.taler";,
         payto_uri: "payto://iban/de123123123" as PaytoString,
       },
       {
-        aml_status: 2,
+        exchange_http_status: 2,
         exchange_url: "http://exchange.taler";,
         payto_uri: "payto://iban/de123123123" as PaytoString,
       },
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx
index 3eeed1d7b..16bbd4b18 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx
@@ -119,18 +119,11 @@ function PendingTable({ entries }: PendingTableProps): 
VNode {
                   <td>{e.exchange_url}</td>
                   <td>{e.payto_uri}</td>
                   <td>
-                    {e.aml_status === 1 ? (
-                      <i18n.Translate>
-                        There is an anti-money laundering process pending to
-                        complete.
-                      </i18n.Translate>
-                    ) : (
-                      <i18n.Translate>
-                        The account is frozen due to the anti-money laundering
-                        rules. Contact the exchange service provider for 
further
-                        instructions.
-                      </i18n.Translate>
-                    )}
+                    <i18n.Translate>
+                      There is an anti-money laundering process pending to
+                      complete.
+                    </i18n.Translate>
+
                   </td>
                 </tr>
               );
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
index 0ce2c331d..0dc125706 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx
@@ -103,14 +103,37 @@ export default function OrderCreate({ onConfirm, onBack 
}: Props): VNode {
               if (resp.type === "ok") {
                 return onConfirm(resp.body.order_id);
               } else {
-                setNotif({
-                  message: i18n.str`Could not create order`,
-                  type: "ERROR",
-                  description:
-                    resp.case === HttpStatusCode.Gone
-                      ? i18n.str`No more stock for product with id 
"${resp.body.product_id}".`
-                      : resp.detail?.hint,
-                });
+                switch (resp.case) {
+                  case HttpStatusCode.UnavailableForLegalReasons: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: i18n.str`No exchange would accept a payment 
because of KYC requirements.`
+                    });
+                    return;
+                  }
+                  case HttpStatusCode.Unauthorized:
+                  case HttpStatusCode.NotFound:
+                  case HttpStatusCode.Conflict: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: resp.detail?.hint,
+                    });
+                    return;
+                  }
+                  case HttpStatusCode.Gone: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: i18n.str`No more stock for product with id 
"${resp.body.product_id}".`
+                    });
+                    return;
+                  }
+                  default: {
+                    assertUnreachable(resp)
+                  }
+                }
               }
             })
             .catch((error) => {
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
index 5da500dc0..c7edce834 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx
@@ -89,11 +89,31 @@ export default function Update({ oid, onBack }: Props): 
VNode {
                   type: "SUCCESS",
                 });
               } else {
-                setNotif({
-                  message: i18n.str`Could not create the refund`,
-                  type: "ERROR",
-                  description: resp.detail?.hint,
-                });
+                switch (resp.case) {
+                  case HttpStatusCode.UnavailableForLegalReasons: {
+                    setNotif({
+                      message: i18n.str`Could not create the refund`,
+                      type: "ERROR",
+                      description: i18n.str`There are pending KYC 
requirements.`
+                    });
+                    return;
+                  }
+                  case HttpStatusCode.Unauthorized:
+                  case HttpStatusCode.Forbidden:
+                  case HttpStatusCode.NotFound:
+                  case HttpStatusCode.Conflict:
+                  case HttpStatusCode.Gone: {
+                    setNotif({
+                      message: i18n.str`Could not create the refund`,
+                      type: "ERROR",
+                      description: resp.detail?.hint,
+                    });
+                    return;
+                  }
+                  default: {
+                    assertUnreachable(resp)
+                  }
+                }
               }
             })
             .catch((error) =>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
index 450585a9f..787512e2a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
@@ -164,11 +164,33 @@ export default function OrderList({ onCreate, onSelect }: 
Props): VNode {
                     type: "SUCCESS",
                   });
                 } else {
-                  setNotif({
-                    message: i18n.str`Could not create the refund`,
-                    type: "ERROR",
-                    description: resp.detail?.hint,
-                  });
+                  switch (resp.case) {
+                    case HttpStatusCode.UnavailableForLegalReasons: {
+                      setNotif({
+                        message: i18n.str`Could not create the refund`,
+                        type: "ERROR",
+                        description: i18n.str`There are pending KYC 
requirements.`
+                      });
+                      return;
+                    }
+                    case HttpStatusCode.Unauthorized:
+                    case HttpStatusCode.Forbidden:
+                    case HttpStatusCode.NotFound:
+                    case HttpStatusCode.Conflict:
+                    case HttpStatusCode.Gone: {
+                      setNotif({
+                        message: i18n.str`Could not create the refund`,
+                        type: "ERROR",
+                        description: resp.detail?.hint,
+                      });
+                      return;
+                    }
+                    default: {
+                      assertUnreachable(resp)
+                    }
+  
+                  }
+
                 }
               })
               .catch((error) =>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
index e8a0c3eba..504932ecb 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx
@@ -87,14 +87,37 @@ export default function TemplateUsePage({
               if (resp.type === "ok") {
                 onOrderCreated(resp.body.order_id)
               } else {
-                setNotif({
-                  message: i18n.str`Could not create order from template`,
-                  type: "ERROR",
-                  description:
-                    resp.case === HttpStatusCode.Gone
-                      ? i18n.str`No more stock for product with id 
"${resp.body.product_id}".`
-                      : resp.detail?.hint,
-                });
+                switch (resp.case) {
+                  case HttpStatusCode.UnavailableForLegalReasons: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: i18n.str`No exchange would accept a payment 
because of KYC requirements.`
+                    });
+                    return;
+                  }
+                  case HttpStatusCode.Unauthorized:
+                  case HttpStatusCode.NotFound:
+                  case HttpStatusCode.Conflict: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: resp.detail?.hint,
+                    });
+                    return;
+                  }
+                  case HttpStatusCode.Gone: {
+                    setNotif({
+                      message: i18n.str`Could not create order`,
+                      type: "ERROR",
+                      description: i18n.str`No more stock for product with id 
"${resp.body.product_id}".`
+                    });
+                    return;
+                  }
+                  default: {
+                    assertUnreachable(resp)
+                  }
+                }
               }
             })
             .catch((error) => {
diff --git a/packages/taler-harness/src/harness/helpers.ts 
b/packages/taler-harness/src/harness/helpers.ts
index 5a119b462..488be33fa 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -1063,7 +1063,7 @@ export async function postAmlDecision(
     justification: "Bla",
     keep_investigating: false,
     new_rules: req.newRules,
-    new_measure: req.newMeasure,
+    new_measures: req.newMeasure,
     properties: {
       foo: "42",
     },
diff --git a/packages/taler-util/src/http-client/exchange.ts 
b/packages/taler-util/src/http-client/exchange.ts
index ec66e5fca..cf340101e 100644
--- a/packages/taler-util/src/http-client/exchange.ts
+++ b/packages/taler-util/src/http-client/exchange.ts
@@ -87,7 +87,7 @@ export type ReservePub = string & { [__pubId]: true };
  */
 export class TalerExchangeHttpClient {
   httpLib: HttpRequestLibrary;
-  public readonly PROTOCOL_VERSION = "20:0:0";
+  public readonly PROTOCOL_VERSION = "21:0:0";
   cacheEvictor: CacheEvictor<TalerExchangeCacheEviction>;
 
   constructor(
@@ -631,21 +631,25 @@ export class TalerExchangeHttpClient {
   }
 
   /**
-   * https://docs.taler.net/core/api-exchange.html#post--kyc-wallet
+   * https://docs.taler.net/core/api-exchange.html#get--kyc-check-$H_PAYTO
    *
    */
   async checkKycStatus(
     account: ReserveAccount,
-    requirementId: number,
+    paytoHash: string,
     params: {
       timeout?: number;
+      awaitAuth?: boolean;
     } = {},
   ) {
-    const url = new URL(`kyc-check/${String(requirementId)}`, this.baseUrl);
+    const url = new URL(`kyc-check/${paytoHash}`, this.baseUrl);
 
     if (params.timeout !== undefined) {
       url.searchParams.set("timeout_ms", String(params.timeout));
     }
+    if (params.awaitAuth !== undefined) {
+      url.searchParams.set("await_auth", params.awaitAuth ? "YES" : "NO");
+    }
 
     const resp = await this.httpLib.fetch(url.href, {
       method: "GET",
@@ -1052,8 +1056,8 @@ function buildAMLDecisionSignature(
     .put(hash(stringToBytes(canonicalJson(decision.properties) + "\0")))
     .put(hash(stringToBytes(canonicalJson(decision.new_rules) + "\0")))
     .put(
-      decision.new_measure != null
-        ? hash(stringToBytes(decision.new_measure))
+      decision.new_measures != null
+        ? hash(stringToBytes(decision.new_measures))
         : zero,
     )
     .put(bufferForUint64(decision.keep_investigating ? 1 : 0))
diff --git a/packages/taler-util/src/http-client/merchant.ts 
b/packages/taler-util/src/http-client/merchant.ts
index e765d286b..736ca85e1 100644
--- a/packages/taler-util/src/http-client/merchant.ts
+++ b/packages/taler-util/src/http-client/merchant.ts
@@ -45,6 +45,7 @@ import {
   codecForOtpDeviceSummaryResponse,
   codecForOutOfStockResponse,
   codecForPaidRefundStatusResponse,
+  codecForPaymentDeniedLegallyResponse,
   codecForPaymentResponse,
   codecForPostOrderResponse,
   codecForProductDetail,
@@ -137,7 +138,7 @@ export enum TalerMerchantManagementCacheEviction {
  * Uses libtool's current:revision:age versioning.
  */
 export class TalerMerchantInstanceHttpClient {
-  public readonly PROTOCOL_VERSION = "16:0:0";
+  public readonly PROTOCOL_VERSION = "17:0:0";
 
   readonly httpLib: HttpRequestLibrary;
   readonly cacheEvictor: CacheEvictor<TalerMerchantInstanceCacheEviction>;
@@ -276,6 +277,8 @@ export class TalerMerchantInstanceHttpClient {
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.GatewayTimeout:
         return opKnownHttpFailure(resp.status, resp);
+      case HttpStatusCode.UnavailableForLegalReasons:
+        return opKnownAlternativeFailure(resp, resp.status, 
codecForPaymentDeniedLegallyResponse())
       default:
         return opUnknownFailure(resp, await readTalerErrorResponse(resp));
     }
@@ -431,6 +434,8 @@ export class TalerMerchantInstanceHttpClient {
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.NotFound:
         return opKnownHttpFailure(resp.status, resp);
+      case HttpStatusCode.UnavailableForLegalReasons:
+        return opKnownAlternativeFailure(resp, resp.status, 
codecForPaymentDeniedLegallyResponse())
       default:
         return opUnknownFailure(resp, await readTalerErrorResponse(resp));
     }
@@ -1234,6 +1239,8 @@ export class TalerMerchantInstanceHttpClient {
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.Unauthorized: // FIXME: missing in docs
         return opKnownHttpFailure(resp.status, resp);
+      case HttpStatusCode.UnavailableForLegalReasons:
+        return opKnownAlternativeFailure(resp, resp.status, 
codecForPaymentDeniedLegallyResponse())
       case HttpStatusCode.Conflict:
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.Gone:
@@ -1471,6 +1478,8 @@ export class TalerMerchantInstanceHttpClient {
         return opKnownHttpFailure(resp.status, resp);
       case HttpStatusCode.Conflict:
         return opKnownHttpFailure(resp.status, resp);
+      case HttpStatusCode.UnavailableForLegalReasons:
+        return opKnownAlternativeFailure(resp, resp.status, 
codecForPaymentDeniedLegallyResponse())
       default:
         return opUnknownFailure(resp, await readTalerErrorResponse(resp));
     }
diff --git a/packages/taler-util/src/taler-signatures.ts 
b/packages/taler-util/src/taler-signatures.ts
index 5c9690528..f529a456b 100644
--- a/packages/taler-util/src/taler-signatures.ts
+++ b/packages/taler-util/src/taler-signatures.ts
@@ -50,8 +50,8 @@ export function signAmlDecision(
   builder.put(hash(stringToBytes(decision.justification)));
   builder.put(hash(stringToBytes(canonicalJson(decision.properties) + "\0")));
   builder.put(hash(stringToBytes(canonicalJson(decision.new_rules) + "\0")));
-  if (decision.new_measure != null) {
-    builder.put(hash(stringToBytes(decision.new_measure)));
+  if (decision.new_measures != null) {
+    builder.put(hash(stringToBytes(decision.new_measures)));
   } else {
     builder.put(new Uint8Array(64));
   }
diff --git a/packages/taler-util/src/types-taler-exchange.ts 
b/packages/taler-util/src/types-taler-exchange.ts
index 2bff19063..671b81d73 100644
--- a/packages/taler-util/src/types-taler-exchange.ts
+++ b/packages/taler-util/src/types-taler-exchange.ts
@@ -1412,6 +1412,25 @@ export interface MeasureInformation {
 
   // Context for the check. Optional.
   context?: Object;
+
+  // Operation that this measure relates to.
+  // NULL if unknown. Useful as a hint to the
+  // user if there are many (voluntary) measures
+  // and some related to unlocking certain operations.
+  // (and due to zero-amount thresholds, no measure
+  // was actually specifically triggered).
+  //
+  // Must be one of "WITHDRAW", "DEPOSIT",
+  // (p2p) "MERGE", (wallet) "BALANCE",
+  // (reserve) "CLOSE", "AGGREGATE",
+  // "TRANSACTION" or "REFUND".
+  // New in protocol **v21**.
+  operation_type?: string;
+
+  // Can this measure be undertaken voluntarily?
+  // Optional, default is false.
+  // Since protocol **vATTEST**.
+  voluntary?: boolean;
 }
 
 export interface AmlProgramRequirement {
@@ -1597,6 +1616,8 @@ export interface LegitimizationNeededResponse {
 
   // Hash of the payto:// account URI for which KYC
   // is required.
+  // The account holder can uses the /kyc-check/$H_PAYTO
+  // endpoint to check the KYC status or initiate the KYC process.
   h_payto: PaytoHash;
 
   // Public key associated with the account. The client must sign
@@ -1611,12 +1632,12 @@ export interface LegitimizationNeededResponse {
   account_pub?: EddsaPublicKeyString;
 
   // Identifies a set of measures that were triggered and that are
-  // now preventing this operation from proceeding.  Gives the
-  // account holder a starting point for understanding why the
-  // transaction was blocked and how to lift it. The account holder
-  // should use the number to check for the account's AML/KYC status
-  // using the /kyc-check/$REQUIREMENT_ROW endpoint.
-  requirement_row: Integer | undefined;
+  // now preventing this operation from proceeding.  Gives developers
+  // a starting point for understanding why the transaction was
+  // blocked and how to lift it.
+  // Can be zero (which means there is no requirement row),
+  // especially if bad_kyc_auth is set.
+  requirement_row: Integer;
 
   // True if the operation was denied because the
   // KYC auth key does not match the merchant public
@@ -1686,7 +1707,8 @@ export interface AccountLimit {
   // Clients that are aware of hard limits *should*
   // inform users about the hard limit and prevent flows
   // in the UI that would cause violations of hard limits.
-  soft_limit: boolean;
+  // Made optional in **v21** with a default of 'false' if missing.
+  soft_limit?: boolean;
 }
 
 export interface KycProcessClientInformation {
@@ -1854,6 +1876,12 @@ export interface AmlDecisionRequest {
   // Identifies a GNU Taler wallet or an affected bank account.
   h_payto: PaytoHash;
 
+  // Payto address of the account the decision is about.
+  // Optional. Must be given if the account is not yet
+  // known to the exchange. If given, must match h_payto.
+  // New since protocol **v21**.
+  payto_uri?: string;
+
   // What are the new rules?
   // New since protocol **v20**.
   new_rules: LegitimizationRuleSet;
@@ -1862,14 +1890,14 @@ export interface AmlDecisionRequest {
   // New since protocol **v20**.
   properties: AccountProperties;
 
-  // New measure to apply immediately to the account.
+  // Space-separated list of measures to trigger
+  // immediately on the account.
+  // Prefixed with a "+" to indicate that the
+  // measures should be ANDed.
   // Should typically be used to give the user some
   // information or request additional information.
-  // Use "verboten" to communicate to the customer
-  // that there is no KYC check that could be passed
-  // to modify the new_rules.
-  // New since protocol **v20**.
-  new_measure?: string;
+  // New since protocol **v21**.
+  new_measures?: string;
 
   // True if the account should remain under investigation by AML staff.
   // New since protocol **v20**.
@@ -1969,10 +1997,6 @@ export interface ExchangeKeysResponse {
   // The exchange's currency or asset unit.
   currency: string;
 
-  /**
-   * FIXME: PARTIALLY IMPLEMENTED!!
-   */
-
   // How wallets should render this currency.
   currency_specification: CurrencySpecification;
 
@@ -2009,7 +2033,7 @@ export interface ExchangeKeysResponse {
 
   // List of exchanges that this exchange is partnering
   // with to enable wallet-to-wallet transfers.
-  wads: ExchangePartner[];
+  wads: ExchangePartnerListEntry[];
 
   // EdDSA master public key of the exchange, used to sign entries
   // in denoms and signkeys.
@@ -2020,11 +2044,26 @@ export interface ExchangeKeysResponse {
   reserve_closing_delay: RelativeTime;
 
   // Threshold amounts beyond which wallet should
-  // trigger the KYC process of the issuing
-  // exchange.  Optional option, if not given there is no limit.
+  // trigger the KYC process of the issuing exchange.
+  // Optional option, if not given there is no limit.
   // Currency must match currency.
   wallet_balance_limit_without_kyc?: AmountString[];
 
+  // Array of limits that apply to all accounts.
+  // All of the given limits will be hard limits.
+  // Wallets and merchants are expected to obey them
+  // and not even allow the user to cross them.
+  // Since protocol **v21**.
+  hard_limits: AccountLimit[];
+
+  // Array of limits with a soft threshold of zero
+  // that apply to all accounts without KYC.
+  // Wallets and merchants are expected to trigger
+  // a KYC process before attempting any zero-limited
+  // operations.
+  // Since protocol **v21**.
+  zero_limits: ZeroLimitedOperation[];
+
   // Denominations offered by this exchange
   denominations: DenomGroup[];
 
@@ -2065,6 +2104,18 @@ export interface ExchangeKeysResponse {
   extensions_sig?: EddsaSignature;
 }
 
+interface ZeroLimitedOperation {
+
+  // Operation that is limited to an amount of
+  // zero until the client has passed some KYC check.
+  // Must be one of "WITHDRAW", "DEPOSIT",
+  // (p2p) "MERGE", (wallet) "BALANCE",
+  // (reserve) "CLOSE", "AGGREGATE",
+  // "TRANSACTION" or "REFUND".
+  operation_type: string;
+
+}
+
 interface ExtensionManifest {
   // The criticality of the extension MUST be provided.  It has the same
   // semantics as "critical" has for extensions in X.509:
@@ -2198,7 +2249,7 @@ export interface AggregateTransferFee {
   sig: EddsaSignatureString;
 }
 
-interface ExchangePartner {
+interface ExchangePartnerListEntry {
   // Base URL of the partner exchange.
   partner_base_url: string;
 
@@ -2268,6 +2319,8 @@ export const codecForExchangeConfig = (): 
Codec<ExchangeVersionResponse> =>
     .property("currency_specification", codecForCurrencySpecificiation())
     .property("supported_kyc_requirements", codecForList(codecForString()))
     .build("TalerExchangeApi.ExchangeVersionResponse");
+
+// FIXME: complete the codec to check for valid exchange response
 export const codecForExchangeKeys = (): Codec<ExchangeKeysResponse> =>
   buildCodecForObject<ExchangeKeysResponse>()
     .property("version", codecForString())
@@ -2277,6 +2330,8 @@ export const codecForExchangeKeys = (): 
Codec<ExchangeKeysResponse> =>
     .property("asset_type", codecForAny())
     .property("auditors", codecForAny())
     .property("currency_specification", codecForAny())
+    .property("zero_limits", codecForAny())
+    .property("hard_limits", codecForAny())
     .property("denominations", codecForAny())
     .property("exchange_pub", codecForAny())
     .property("exchange_sig", codecForAny())
@@ -2294,7 +2349,6 @@ export const codecForExchangeKeys = (): 
Codec<ExchangeKeysResponse> =>
     .property("wads", codecForAny())
     .property("wallet_balance_limit_without_kyc", codecForAny())
     .property("wire_fees", codecForAny())
-
     .build("TalerExchangeApi.ExchangeKeysResponse");
 
 export const codecForEventCounter = (): Codec<EventCounter> =>
@@ -2336,6 +2390,8 @@ export const codecForMeasureInformation = (): 
Codec<MeasureInformation> =>
     .property("prog_name", codecForString())
     .property("check_name", codecForString())
     .property("context", codecForAny())
+    .property("operation_type", codecOptional(codecForString()))
+    .property("voluntary", codecOptional(codecForBoolean()))
     .build("TalerExchangeApi.MeasureInformation");
 
 // export const codecForAmlDecisionDetails = (): Codec<AmlDecisionDetails> =>
@@ -2430,7 +2486,7 @@ export const codecForLegitimizationNeededResponse =
       .property("hint", codecOptional(codecForString()))
       .property("h_payto", codecForString())
       .property("account_pub", codecOptional(codecForString()))
-      .property("requirement_row", codecOptional(codecForNumber()))
+      .property("requirement_row", (codecForNumber()))
       .property("bad_kyc_auth", codecOptional(codecForBoolean()))
       .build("TalerExchangeApi.LegitimizationNeededResponse");
 
@@ -2454,7 +2510,7 @@ export const codecForAccountLimit = (): 
Codec<AccountLimit> =>
     )
     .property("timeframe", codecForDuration)
     .property("threshold", codecForAmountString())
-    .property("soft_limit", codecForBoolean())
+    .property("soft_limit", codecOptional(codecForBoolean()))
     .build("TalerExchangeApi.AccountLimit");
 
 export const codecForKycCheckPublicInformation =
diff --git a/packages/taler-util/src/types-taler-merchant.ts 
b/packages/taler-util/src/types-taler-merchant.ts
index 58cac5e58..de3664b67 100644
--- a/packages/taler-util/src/types-taler-merchant.ts
+++ b/packages/taler-util/src/types-taler-merchant.ts
@@ -29,10 +29,12 @@ import {
 } from "./codec.js";
 import {
   AccessToken,
+  AccountLimit,
   CoinEnvelope,
   ExchangeWireAccount,
   PaytoString,
   buildCodecForUnion,
+  codecForAccountLimit,
   codecForConstNumber,
   codecForConstString,
   codecForEither,
@@ -812,6 +814,16 @@ export interface PaymentResponse {
   // payment.
   pos_confirmation?: string;
 }
+export interface PaymentDeniedLegallyResponse {
+
+  // Base URL of the exchanges that denied the payment.
+  // The wallet should refresh the coins from these
+  // exchanges, but may try to pay with coins from
+  // other exchanges.
+  exchange_base_urls: string[];
+
+}
+
 
 export interface PaymentStatusRequestParams {
   // Hash of the order’s contract terms (this is used to
@@ -1335,17 +1347,55 @@ export interface MerchantAccountKycRedirect {
   // 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.
+  // due to the need for a KYC auth transfer.
+  // (See payto_kycauth in that case.)
   kyc_url?: string;
 
-  // AML status of the account.
-  aml_status: Integer;
+  // Array with limitations that currently apply to this
+  // account and that may be increased or lifted if the
+  // KYC check is passed.
+  // Note that additional limits *may* exist and not be
+  // communicated to the client. If such limits are
+  // reached, this *may* be indicated by the account
+  // going into aml_review state. However, it is
+  // also possible that the exchange may legally have
+  // to deny operations without being allowed to provide
+  // any justification.
+  // The limits should be used by the client to
+  // possibly structure their operations (e.g. withdraw
+  // what is possible below the limit, ask the user to
+  // pass KYC checks or withdraw the rest after the time
+  // limit is passed, warn the user to not withdraw too
+  // much or even prevent the user from generating a
+  // request that would cause it to exceed hard limits).
+  limits?: AccountLimit[];
 
   // 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.
+  // Optional (as there may not always have
+  // been an error code). Since protocol **v17**.
+  exchange_code?: number;
+
+  // HTTP status code returned by the exchange when we asked for
+  // information about the KYC status.
+  // Since protocol **v17**.
+  exchange_http_status: number;
+
   // Our bank wire account this is about.
   payto_uri: PaytoString;
+
+  // Array of wire transfer instructions (including
+  // optional amount and subject) for a KYC auth wire
+  // transfer. Set only if this is required
+  // to get the given exchange working.
+  // Array because the exchange may have multiple
+  // bank accounts, in which case any of these
+  // accounts will do.
+  // Optional. Since protocol **v17**.
+  payto_kycauths?: string[];
 }
 
 export interface ExchangeKycTimeout {
@@ -2823,6 +2873,11 @@ export const codecForPaymentResponse = (): 
Codec<PaymentResponse> =>
     .property("sig", codecForString())
     .build("TalerMerchantApi.PaymentResponse");
 
+export const codecForPaymentDeniedLegallyResponse = (): 
Codec<PaymentDeniedLegallyResponse> =>
+  buildCodecForObject<PaymentDeniedLegallyResponse>()
+    .property("exchange_base_urls", codecForList(codecForString()))
+    .build("TalerMerchantApi.PaymentDeniedLegallyResponse");
+
 export const codecForStatusPaid = (): Codec<StatusPaid> =>
   buildCodecForObject<StatusPaid>()
     .property("refund_amount", codecForAmountString())
@@ -2968,10 +3023,13 @@ export const codecForAccountKycRedirects = (): 
Codec<AccountKycRedirects> =>
 export const codecForMerchantAccountKycRedirect =
   (): Codec<MerchantAccountKycRedirect> =>
     buildCodecForObject<MerchantAccountKycRedirect>()
-      .property("kyc_url", codecForURLString())
-      .property("aml_status", codecForNumber())
+      .property("kyc_url", codecOptional(codecForURLString()))
+      .property("limits", codecOptional(codecForList(codecForAccountLimit())))
       .property("exchange_url", codecForURLString())
+      .property("exchange_code", codecForNumber())
+      .property("exchange_http_status", codecForNumber())
       .property("payto_uri", codecForPaytoString())
+      .property("payto_kycauths", 
codecOptional(codecForList(codecForString())))
       .build("TalerMerchantApi.MerchantAccountKycRedirect");
 
 export const codecForExchangeKycTimeout = (): Codec<ExchangeKycTimeout> =>

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