aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-util
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-08-08 16:49:37 +0200
committerFlorian Dold <florian@dold.me>2024-08-14 13:22:41 +0200
commit3c86bfb1435deba091771ca4e6135fbfd29b70ec (patch)
tree1f7833e9a903deb90f040f8e73663e5f104e945a /packages/taler-util
parent947aa424ca0bc214c3e175221636fe6193c939c2 (diff)
wallet-core: implement basic wallet KYC for balance thresholds
Diffstat (limited to 'packages/taler-util')
-rw-r--r--packages/taler-util/src/http-client/exchange.ts10
-rw-r--r--packages/taler-util/src/http-common.ts10
-rw-r--r--packages/taler-util/src/index.ts108
-rw-r--r--packages/taler-util/src/operation.ts4
-rw-r--r--packages/taler-util/src/payto.ts7
-rw-r--r--packages/taler-util/src/taler-crypto.ts17
-rw-r--r--packages/taler-util/src/taler-signatures.ts63
-rw-r--r--packages/taler-util/src/types-taler-exchange.ts208
-rw-r--r--packages/taler-util/src/types-taler-wallet-transactions.ts1
-rw-r--r--packages/taler-util/src/types-taler-wallet.ts46
10 files changed, 281 insertions, 193 deletions
diff --git a/packages/taler-util/src/http-client/exchange.ts b/packages/taler-util/src/http-client/exchange.ts
index 4a27c824f..0539319c3 100644
--- a/packages/taler-util/src/http-client/exchange.ts
+++ b/packages/taler-util/src/http-client/exchange.ts
@@ -298,7 +298,6 @@ export class TalerExchangeHttpClient {
async uploadKycForm(requirement: KycRequirementInformationId, body: object) {
const url = new URL(`kyc-upload/${requirement}`, this.baseUrl);
-
const resp = await this.httpLib.fetch(url.href, {
method: "POST",
body,
@@ -627,8 +626,7 @@ export class TalerExchangeHttpClient {
function buildKYCQuerySignature(key: SigningKey): string {
const sigBlob = buildSigPS(
- TalerSignaturePurpose.TALER_SIGNATURE_AML_QUERY,
- // TalerSignaturePurpose.TALER_SIGNATURE_WALLET_ACCOUNT_SETUP,
+ TalerSignaturePurpose.AML_QUERY,
).build();
return encodeCrock(eddsaSign(sigBlob, key));
@@ -636,7 +634,7 @@ function buildKYCQuerySignature(key: SigningKey): string {
function buildAMLQuerySignature(key: SigningKey): string {
const sigBlob = buildSigPS(
- TalerSignaturePurpose.TALER_SIGNATURE_AML_QUERY,
+ TalerSignaturePurpose.AML_QUERY,
).build();
return encodeCrock(eddsaSign(sigBlob, key));
@@ -648,7 +646,7 @@ function buildAMLDecisionSignature(
): AmlDecisionRequest {
const zero = new Uint8Array(new ArrayBuffer(64));
- const sigBlob = buildSigPS(TalerSignaturePurpose.TALER_SIGNATURE_AML_DECISION)
+ const sigBlob = buildSigPS(TalerSignaturePurpose.AML_DECISION)
//TODO: new need the null terminator, also in the exchange
.put(hash(stringToBytes(decision.justification))) //check null
.put(timestampRoundedToBuffer(decision.decision_time))
@@ -664,5 +662,3 @@ function buildAMLDecisionSignature(
officer_sig,
};
}
-
-
diff --git a/packages/taler-util/src/http-common.ts b/packages/taler-util/src/http-common.ts
index 20ac9dddd..6f537dda2 100644
--- a/packages/taler-util/src/http-common.ts
+++ b/packages/taler-util/src/http-common.ts
@@ -274,10 +274,10 @@ export async function readSuccessResponseJsonOrErrorCode<T>(
};
}
-export async function readResponseJsonOrErrorCode<T>(
+export async function readResponseJsonOrThrow<T>(
httpResponse: HttpResponse,
codec: Codec<T>,
-): Promise<{ isError: boolean; response: T }> {
+): Promise<T> {
let respJson;
try {
respJson = await httpResponse.json();
@@ -310,13 +310,9 @@ export async function readResponseJsonOrErrorCode<T>(
"Response invalid",
);
}
- return {
- isError: !(httpResponse.status >= 200 && httpResponse.status < 300),
- response: parsedResponse,
- };
+ return parsedResponse;
}
-
type HttpErrorDetails = {
requestUrl: string;
requestMethod: string;
diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts
index 025ce0183..d6a2fa614 100644
--- a/packages/taler-util/src/index.ts
+++ b/packages/taler-util/src/index.ts
@@ -2,59 +2,59 @@ import { TalerErrorCode } from "./taler-error-codes.js";
export { TalerErrorCode };
-export * from "./CancellationToken.js";
-export * from "./MerchantApiClient.js";
-export { RequestThrottler } from "./RequestThrottler.js";
-export * from "./ReserveStatus.js";
-export * from "./ReserveTransaction.js";
-export { TaskThrottler } from "./TaskThrottler.js";
-export * from "./amounts.js";
-export * from "./bank-api-client.js";
-export * from "./base64.js";
-export * from "./bitcoin.js";
-export * from "./codec.js";
-export * from "./contract-terms.js";
-export * from "./errors.js";
-export { fnutil } from "./fnutils.js";
-export * from "./helpers.js";
-export * from "./http-client/authentication.js";
-export * from "./http-client/bank-conversion.js";
-export * from "./http-client/bank-core.js";
-export * from "./http-client/bank-integration.js";
-export * from "./http-client/bank-revenue.js";
-export * from "./http-client/bank-wire.js";
-export * from "./http-client/challenger.js";
-export * from "./http-client/exchange.js";
-export * from "./http-client/merchant.js";
-export * from "./http-client/officer-account.js";
-export { CacheEvictor } from "./http-client/utils.js";
-export * from "./http-status-codes.js";
-export * from "./i18n.js";
-export * from "./iban.js";
-export * from "./invariants.js";
-export * from "./kdf.js";
-export * from "./libtool-version.js";
-export * from "./logging.js";
-export {
- crypto_sign_keyPair_fromSeed,
- randomBytes,
- secretbox,
- secretbox_open,
- setPRNG,
-} from "./nacl-fast.js";
-export * from "./notifications.js";
-export * from "./observability.js";
-export * from "./operation.js";
-export * from "./payto.js";
-export * from "./promises.js";
-export * from "./qr.js";
-export * from "./rfc3548.js";
-export * from "./taler-crypto.js";
-export * from "./taleruri.js";
-export * from "./time.js";
-export * from "./timer.js";
-export * from "./transaction-test-data.js";
-export * from "./url.js";
+ export * from "./amounts.js";
+ export * from "./bank-api-client.js";
+ export * from "./base64.js";
+ export * from "./bitcoin.js";
+ export * from "./CancellationToken.js";
+ export * from "./codec.js";
+ export * from "./contract-terms.js";
+ export * from "./errors.js";
+ export { fnutil } from "./fnutils.js";
+ export * from "./helpers.js";
+ export * from "./http-client/authentication.js";
+ export * from "./http-client/bank-conversion.js";
+ export * from "./http-client/bank-core.js";
+ export * from "./http-client/bank-integration.js";
+ export * from "./http-client/bank-revenue.js";
+ export * from "./http-client/bank-wire.js";
+ export * from "./http-client/challenger.js";
+ export * from "./http-client/exchange.js";
+ export * from "./http-client/merchant.js";
+ export * from "./http-client/officer-account.js";
+ export { CacheEvictor } from "./http-client/utils.js";
+ export * from "./http-status-codes.js";
+ export * from "./i18n.js";
+ export * from "./iban.js";
+ export * from "./invariants.js";
+ export * from "./kdf.js";
+ export * from "./libtool-version.js";
+ export * from "./logging.js";
+ export * from "./MerchantApiClient.js";
+ export {
+ crypto_sign_keyPair_fromSeed,
+ randomBytes,
+ secretbox,
+ secretbox_open,
+ setPRNG
+ } from "./nacl-fast.js";
+ export * from "./notifications.js";
+ export * from "./observability.js";
+ export * from "./operation.js";
+ export * from "./payto.js";
+ export * from "./promises.js";
+ export * from "./qr.js";
+ export { RequestThrottler } from "./RequestThrottler.js";
+ export * from "./ReserveStatus.js";
+ export * from "./ReserveTransaction.js";
+ export * from "./rfc3548.js";
+ export * from "./taler-crypto.js";
+ export * from "./taleruri.js";
+ export { TaskThrottler } from "./TaskThrottler.js";
+ export * from "./time.js";
+ export * from "./timer.js";
+ export * from "./transaction-test-data.js";
+ export * from "./url.js";
export * from "./types-taler-bank-conversion.js";
export * from "./types-taler-bank-integration.js";
@@ -74,3 +74,5 @@ export * as TalerExchangeApi from "./types-taler-exchange.js";
export * as TalerMerchantApi from "./types-taler-merchant.js";
export * as TalerRevenueApi from "./types-taler-revenue.js";
export * as TalerWireGatewayApi from "./types-taler-wire-gateway.js";
+
+export * from "./taler-signatures.js";
diff --git a/packages/taler-util/src/operation.ts b/packages/taler-util/src/operation.ts
index 2d17238dc..6b5eb61a6 100644
--- a/packages/taler-util/src/operation.ts
+++ b/packages/taler-util/src/operation.ts
@@ -19,7 +19,7 @@
*/
import {
HttpResponse,
- readResponseJsonOrErrorCode,
+ readResponseJsonOrThrow,
readSuccessResponseJsonOrThrow,
readTalerErrorResponse,
} from "./http-common.js";
@@ -127,7 +127,7 @@ export async function opKnownAlternativeFailure<T extends HttpStatusCode, B>(
s: T,
codec: Codec<B>,
): Promise<OperationAlternative<T, B>> {
- const body = (await readResponseJsonOrErrorCode(resp, codec)).response;
+ const body = await readResponseJsonOrThrow(resp, codec);
return { type: "fail", case: s, body };
}
diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts
index 3a332b37e..f50f97e58 100644
--- a/packages/taler-util/src/payto.ts
+++ b/packages/taler-util/src/payto.ts
@@ -25,7 +25,6 @@ import {
} from "./codec.js";
import {
AccessToken,
- bytesToString,
codecForAccessToken,
codecOptional,
hashTruncate32,
@@ -214,9 +213,9 @@ export function stringifyPaytoUri(p: PaytoUri): PaytoString {
return url.href as PaytoString;
}
-export function hashPaytoUri(p: PaytoUri): string {
- const paytoUri = stringifyPaytoUri(p);
- return bytesToString(hashTruncate32(stringToBytes(paytoUri + "\0")));
+export function hashPaytoUri(p: PaytoUri | string): Uint8Array {
+ const paytoUri = typeof p === "string" ? p : stringifyPaytoUri(p);
+ return hashTruncate32(stringToBytes(paytoUri + "\0"));
}
/**
diff --git a/packages/taler-util/src/taler-crypto.ts b/packages/taler-util/src/taler-crypto.ts
index d4e21e646..ca57e22e2 100644
--- a/packages/taler-util/src/taler-crypto.ts
+++ b/packages/taler-util/src/taler-crypto.ts
@@ -31,11 +31,12 @@ import { Logger } from "./logging.js";
import * as nacl from "./nacl-fast.js";
import { secretbox } from "./nacl-fast.js";
import { TalerProtocolDuration, TalerProtocolTimestamp } from "./time.js";
+import { CoinPublicKeyString, HashCodeString } from "./types-taler-common.js";
import {
- CoinPublicKeyString,
- HashCodeString,
-} from "./types-taler-common.js";
-import { CoinEnvelope, DenomKeyType, DenominationPubKey } from "./types-taler-exchange.js";
+ CoinEnvelope,
+ DenomKeyType,
+ DenominationPubKey,
+} from "./types-taler-exchange.js";
export type Flavor<T, FlavorT extends string> = T & {
_flavor?: `taler.${FlavorT}`;
@@ -985,6 +986,7 @@ export enum TalerSignaturePurpose {
MERCHANT_REFUND = 1102,
WALLET_COIN_RECOUP = 1203,
WALLET_COIN_LINK = 1204,
+ WALLET_ACCOUNT_SETUP = 1205,
WALLET_COIN_RECOUP_REFRESH = 1206,
WALLET_AGE_ATTESTATION = 1207,
WALLET_PURSE_CREATE = 1210,
@@ -996,9 +998,10 @@ export enum TalerSignaturePurpose {
WALLET_COIN_HISTORY = 1209,
EXCHANGE_CONFIRM_RECOUP = 1039,
EXCHANGE_CONFIRM_RECOUP_REFRESH = 1041,
- TALER_SIGNATURE_AML_DECISION = 1350,
- TALER_SIGNATURE_AML_QUERY = 1351,
- TALER_SIGNATURE_MASTER_AML_KEY = 1017,
+ AML_DECISION = 1350,
+ AML_QUERY = 1351,
+ MASTER_AML_KEY = 1017,
+ KYC_AUTH = 1360,
ANASTASIS_POLICY_UPLOAD = 1400,
ANASTASIS_POLICY_DOWNLOAD = 1401,
SYNC_BACKUP_UPLOAD = 1450,
diff --git a/packages/taler-util/src/taler-signatures.ts b/packages/taler-util/src/taler-signatures.ts
new file mode 100644
index 000000000..81b7c242e
--- /dev/null
+++ b/packages/taler-util/src/taler-signatures.ts
@@ -0,0 +1,63 @@
+/*
+ This file is part of GNU Taler
+ (C) 2024 GNUnet e.V.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { canonicalJson } from "./index.js";
+import {
+ bufferForUint64,
+ buildSigPS,
+ decodeCrock,
+ eddsaSign,
+ hash,
+ stringToBytes,
+ TalerSignaturePurpose,
+ timestampRoundedToBuffer,
+} from "./taler-crypto.js";
+import { AmlDecisionRequestWithoutSignature } from "./types-taler-exchange.js";
+
+/**
+ * Implementation of Taler protocol signatures.
+ *
+ * In this file, we have implementations of signatures that are not used in the wallet,
+ * but in other places (tests, SPAs, ...).
+ */
+
+/**
+ * Signature for the POST /aml/$OFFICER_PUB/decisions endpoint.
+ */
+export function signAmlDecision(
+ priv: Uint8Array,
+ decision: AmlDecisionRequestWithoutSignature,
+): Uint8Array {
+ const builder = buildSigPS(TalerSignaturePurpose.AML_DECISION);
+
+ const flags: number = decision.keep_investigating ? 1 : 0;
+
+ builder.put(timestampRoundedToBuffer(decision.decision_time));
+ builder.put(decodeCrock(decision.h_payto));
+ 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)));
+ } else {
+ builder.put(new Uint8Array(64));
+ }
+ builder.put(bufferForUint64(flags));
+
+ const sigBlob = builder.build();
+
+ return eddsaSign(sigBlob, priv);
+}
diff --git a/packages/taler-util/src/types-taler-exchange.ts b/packages/taler-util/src/types-taler-exchange.ts
index b71f302f5..2e13b4024 100644
--- a/packages/taler-util/src/types-taler-exchange.ts
+++ b/packages/taler-util/src/types-taler-exchange.ts
@@ -42,7 +42,6 @@ import { Edx25519PublicKeyEnc } from "./taler-crypto.js";
import {
TalerProtocolDuration,
TalerProtocolTimestamp,
- codecForAbsoluteTime,
codecForDuration,
codecForTimestamp,
} from "./time.js";
@@ -51,9 +50,6 @@ import {
AmlOfficerPublicKeyP,
AmountString,
Base32String,
- codecForAccessToken,
- codecForInternationalizedString,
- codecForURLString,
CoinPublicKeyString,
Cs25519Point,
CurrencySpecification,
@@ -69,6 +65,9 @@ import {
RsaPublicKeySring,
Timestamp,
WireSalt,
+ codecForAccessToken,
+ codecForInternationalizedString,
+ codecForURLString,
} from "./types-taler-common.js";
export type DenominationPubKey = RsaDenominationPubKey | CsDenominationPubKey;
@@ -1387,21 +1386,18 @@ export interface BatchDepositRequestCoin {
}
export interface AvailableMeasureSummary {
-
// Available original measures that can be
// triggered directly by default rules.
- roots: { [measure_name: string]: MeasureInformation; };
+ roots: { [measure_name: string]: MeasureInformation };
// Available AML programs.
- programs: { [prog_name: string]: AmlProgramRequirement; };
+ programs: { [prog_name: string]: AmlProgramRequirement };
// Available KYC checks.
- checks: { [check_name: string]: KycCheckInformation; };
-
+ checks: { [check_name: string]: KycCheckInformation };
}
export interface MeasureInformation {
-
// Name of a KYC check.
check_name: string;
@@ -1410,11 +1406,9 @@ export interface MeasureInformation {
// Context for the check. Optional.
context?: Object;
-
}
export interface AmlProgramRequirement {
-
// Description of what the AML program does.
description: string;
@@ -1428,11 +1422,9 @@ export interface AmlProgramRequirement {
// are the minimum that the check must produce
// (it may produce more).
inputs: string[];
-
}
export interface KycCheckInformation {
-
// Description of the KYC check. Should be shown
// to the AML staff but will also be shown to the
// client when they initiate the check in the KYC SPA.
@@ -1459,7 +1451,6 @@ export interface KycCheckInformation {
fallback: string;
}
-
export interface AmlDecisionDetails {
// Array of AML decisions made for this account. Possibly
// contains only the most recent decision if "history" was
@@ -1469,6 +1460,7 @@ export interface AmlDecisionDetails {
// Array of KYC attributes obtained for this account.
kyc_attributes: KycDetail[];
}
+
export interface AmlDecisionDetail {
// What was the justification given?
justification: string;
@@ -1485,6 +1477,7 @@ export interface AmlDecisionDetail {
// Who made the decision?
decider_pub: AmlOfficerPublicKeyP;
}
+
export interface KycDetail {
// Name of the configuration section that specifies the provider
// which was used to collect the KYC details
@@ -1502,6 +1495,10 @@ export interface KycDetail {
expiration_time: Timestamp;
}
+export type AmlDecisionRequestWithoutSignature = Omit<
+ AmlDecisionRequest,
+ "officer_sig"
+>;
export interface ExchangeVersionResponse {
// libtool-style representation of the Exchange protocol version, see
@@ -1553,7 +1550,6 @@ export interface WireAccount {
}
export interface WalletKycRequest {
-
// Balance threshold (not necessarily exact balance)
// to be crossed by the wallet that (may) trigger
// additional KYC requirements.
@@ -1570,7 +1566,6 @@ export interface WalletKycRequest {
}
export interface WalletKycCheckResponse {
-
// Next balance limit above which a KYC check
// may be required. Optional, not given if no
// threshold exists (assume infinity).
@@ -1580,14 +1575,11 @@ export interface WalletKycCheckResponse {
// expire and the wallet needs to check again
// for updated thresholds.
expiration_time: Timestamp;
-
}
-
// Implemented in this style since exchange
// protocol **v20**.
export interface LegitimizationNeededResponse {
-
// Numeric error code unique to the condition.
// Should always be TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED.
code: number;
@@ -1619,11 +1611,9 @@ export interface LegitimizationNeededResponse {
// should use the number to check for the account's AML/KYC status
// using the /kyc-check/$REQUIREMENT_ROW endpoint.
requirement_row: Integer;
-
}
export interface AccountKycStatus {
-
// Current AML state for the target account. True if
// operations are not happening due to staff processing
// paperwork *or* due to legal requirements (so the
@@ -1661,10 +1651,8 @@ export interface AccountKycStatus {
// much or even prevent the user from generating a
// request that would cause it to exceed hard limits).
limits?: AccountLimit[];
-
}
export interface AccountLimit {
-
// Operation that is limited.
// Must be one of "WITHDRAW", "DEPOSIT", "P2P-RECEIVE"
// or "WALLET-BALANCE".
@@ -1688,13 +1676,12 @@ export interface AccountLimit {
}
export interface KycProcessClientInformation {
-
// Array of requirements.
requirements: KycRequirementInformation[];
// True if the client is expected to eventually satisfy all requirements.
// Default (if missing) is false.
- is_and_combinator?: boolean
+ is_and_combinator?: boolean;
// List of available voluntary checks the client could pay for.
// Since **vATTEST**.
@@ -1702,10 +1689,9 @@ export interface KycProcessClientInformation {
}
declare const opaque_kycReq: unique symbol;
-export type KycRequirementInformationId = string & { [opaque_kycReq]: true }
+export type KycRequirementInformationId = string & { [opaque_kycReq]: true };
export interface KycRequirementInformation {
-
// Which form should be used? Common values include "INFO"
// (to just show the descriptions but allow no action),
// "LINK" (to enable the user to obtain a link via
@@ -1730,7 +1716,6 @@ export interface KycRequirementInformation {
// Since **vATTEST**.
export interface KycCheckPublicInformation {
-
// English description of the check.
description: string;
@@ -1743,7 +1728,6 @@ export interface KycCheckPublicInformation {
// something more??!?
}
-
export interface EventCounter {
// Number of events of the specified type in
// the given range.
@@ -1751,13 +1735,11 @@ export interface EventCounter {
}
export interface AmlDecisionsResponse {
-
// Array of AML decisions matching the query.
records: AmlDecision[];
}
export interface AmlDecision {
-
// Which payto-address is this record about.
// Identifies a GNU Taler wallet or an affected bank account.
h_payto: PaytoHash;
@@ -1788,7 +1770,6 @@ export interface AmlDecision {
// True if this is the active decision for the
// account.
is_active: boolean;
-
}
// All fields in this object are optional. The actual
@@ -1797,7 +1778,6 @@ export interface AmlDecision {
// however, some common fields are standardized
// and thus described here.
export interface AccountProperties {
-
// True if this is a politically exposed account.
// Rules for classifying accounts as politically
// exposed are country-dependent.
@@ -1824,10 +1804,13 @@ export interface AccountProperties {
// Was the client's account reported to the authorities?
was_reported?: boolean;
+ /**
+ * Additional free-form properties.
+ */
+ [x: string]: any;
}
export interface LegitimizationRuleSet {
-
// When does this set of rules expire and
// we automatically transition to the successor
// measure?
@@ -1844,12 +1827,10 @@ export interface LegitimizationRuleSet {
// Custom measures that KYC rules and the
// successor_measure may refer to.
- custom_measures: { [measure_name: string]: MeasureInformation; };
-
+ custom_measures: { [measure_name: string]: MeasureInformation };
}
export interface AmlDecisionRequest {
-
// Human-readable justification for the decision.
justification: string;
@@ -1884,12 +1865,9 @@ export interface AmlDecisionRequest {
// When was the decision made?
decision_time: Timestamp;
-
}
-
export interface KycRule {
-
// Type of operation to which the rule applies.
operation_type: string;
@@ -1932,18 +1910,13 @@ export interface KycRule {
// measure what to do next.
// Default (if missing) is false.
is_and_combinator?: boolean;
-
}
-
export interface KycAttributes {
-
// Matching KYC attribute history of the account.
details: KycAttributeCollectionEvent[];
-
}
export interface KycAttributeCollectionEvent {
-
// Row ID of the record. Used to filter by offset.
rowid: Integer;
@@ -1959,7 +1932,6 @@ export interface KycAttributeCollectionEvent {
// Time when the KYC data was collected
collection_time: Timestamp;
-
}
export enum AmlState {
@@ -2295,18 +2267,18 @@ export const codecForEventCounter = (): Codec<EventCounter> =>
.property("counter", codecForNumber())
.build("TalerExchangeApi.EventCounter");
-
export const codecForAmlDecisionsResponse = (): Codec<AmlDecisionsResponse> =>
buildCodecForObject<AmlDecisionsResponse>()
.property("records", codecForList(codecForAmlDecision()))
.build("TalerExchangeApi.AmlDecisionsResponse");
-export const codecForAvailableMeasureSummary = (): Codec<AvailableMeasureSummary> =>
- buildCodecForObject<AvailableMeasureSummary>()
- .property("checks", codecForMap(codecForKycCheckInformation()))
- .property("programs", codecForMap(codecForAmlProgramRequirement()))
- .property("roots", codecForMap(codecForMeasureInformation()))
- .build("TalerExchangeApi.AvailableMeasureSummary");
+export const codecForAvailableMeasureSummary =
+ (): Codec<AvailableMeasureSummary> =>
+ buildCodecForObject<AvailableMeasureSummary>()
+ .property("checks", codecForMap(codecForKycCheckInformation()))
+ .property("programs", codecForMap(codecForAmlProgramRequirement()))
+ .property("roots", codecForMap(codecForMeasureInformation()))
+ .build("TalerExchangeApi.AvailableMeasureSummary");
export const codecForAmlProgramRequirement = (): Codec<AmlProgramRequirement> =>
buildCodecForObject<AmlProgramRequirement>()
@@ -2376,10 +2348,9 @@ export const codecForAccountProperties = (): Codec<AccountProperties> =>
.property("was_reported", codecOptional(codecForBoolean()))
.build("TalerExchangeApi.AccountProperties");
-
export const codecForLegitimizationRuleSet = (): Codec<LegitimizationRuleSet> =>
buildCodecForObject<LegitimizationRuleSet>()
- .property("expiration_time", (codecForTimestamp))
+ .property("expiration_time", codecForTimestamp)
.property("successor_measure", codecOptional(codecForString()))
.property("rules", codecForList(codecForKycRules()))
.property("custom_measures", codecForMap(codecForMeasureInformation()))
@@ -2396,35 +2367,36 @@ export const codecForKycRules = (): Codec<KycRule> =>
.property("is_and_combinator", codecOptional(codecForBoolean()))
.build("TalerExchangeApi.KycRule");
-
-
export const codecForAmlKycAttributes = (): Codec<KycAttributes> =>
buildCodecForObject<KycAttributes>()
.property("details", codecForList(codecForKycAttributeCollectionEvent()))
.build("TalerExchangeApi.KycAttributes");
-export const codecForKycAttributeCollectionEvent = (): Codec<KycAttributeCollectionEvent> =>
- buildCodecForObject<KycAttributeCollectionEvent>()
- .property("rowid", codecForNumber())
- .property("provider_name", codecOptional(codecForString()))
- .property("collection_time", codecForTimestamp)
- .property("attributes", codecOptional(codecForAny()))
- .build("TalerExchangeApi.KycAttributeCollectionEvent");
-
-export const codecForAmlWalletKycCheckResponse = (): Codec<WalletKycCheckResponse> =>
- buildCodecForObject<WalletKycCheckResponse>()
- .property("next_threshold", codecOptional(codecForAmountString()))
- .property("expiration_time", codecForTimestamp)
- .build("TalerExchangeApi.WalletKycCheckResponse");
-
-export const codecForLegitimizationNeededResponse = (): Codec<LegitimizationNeededResponse> =>
- buildCodecForObject<LegitimizationNeededResponse>()
- .property("code", (codecForNumber()))
- .property("hint", codecOptional(codecForString()))
- .property("h_payto", (codecForString()))
- .property("account_pub", codecOptional(codecForString()))
- .property("requirement_row", (codecForNumber()))
- .build("TalerExchangeApi.LegitimizationNeededResponse");
+export const codecForKycAttributeCollectionEvent =
+ (): Codec<KycAttributeCollectionEvent> =>
+ buildCodecForObject<KycAttributeCollectionEvent>()
+ .property("rowid", codecForNumber())
+ .property("provider_name", codecOptional(codecForString()))
+ .property("collection_time", codecForTimestamp)
+ .property("attributes", codecOptional(codecForAny()))
+ .build("TalerExchangeApi.KycAttributeCollectionEvent");
+
+export const codecForAmlWalletKycCheckResponse =
+ (): Codec<WalletKycCheckResponse> =>
+ buildCodecForObject<WalletKycCheckResponse>()
+ .property("next_threshold", codecOptional(codecForAmountString()))
+ .property("expiration_time", codecForTimestamp)
+ .build("TalerExchangeApi.WalletKycCheckResponse");
+
+export const codecForLegitimizationNeededResponse =
+ (): Codec<LegitimizationNeededResponse> =>
+ buildCodecForObject<LegitimizationNeededResponse>()
+ .property("code", codecForNumber())
+ .property("hint", codecOptional(codecForString()))
+ .property("h_payto", codecForString())
+ .property("account_pub", codecOptional(codecForString()))
+ .property("requirement_row", codecForNumber())
+ .build("TalerExchangeApi.LegitimizationNeededResponse");
export const codecForAccountKycStatus = (): Codec<AccountKycStatus> =>
buildCodecForObject<AccountKycStatus>()
@@ -2435,49 +2407,61 @@ export const codecForAccountKycStatus = (): Codec<AccountKycStatus> =>
export const codecForAccountLimit = (): Codec<AccountLimit> =>
buildCodecForObject<AccountLimit>()
- .property("operation_type", codecForEither(
- codecForConstString("WITHDRAW"),
- codecForConstString("DEPOSIT"),
- codecForConstString("P2P-RECEIVE"),
- codecForConstString("WALLET-BALANCE"))
+ .property(
+ "operation_type",
+ codecForEither(
+ codecForConstString("WITHDRAW"),
+ codecForConstString("DEPOSIT"),
+ codecForConstString("P2P-RECEIVE"),
+ codecForConstString("WALLET-BALANCE"),
+ ),
)
.property("timeframe", codecForDuration)
.property("threshold", codecForAmountString())
.property("soft_limit", codecForBoolean())
.build("TalerExchangeApi.AccountLimit");
-
-export const codecForKycCheckPublicInformation = (): Codec<KycCheckPublicInformation> =>
- buildCodecForObject<KycCheckPublicInformation>()
- .property("description", codecForString())
- .property("description_i18n", codecForInternationalizedString())
- .build("TalerExchangeApi.KycCheckPublicInformation");
+export const codecForKycCheckPublicInformation =
+ (): Codec<KycCheckPublicInformation> =>
+ buildCodecForObject<KycCheckPublicInformation>()
+ .property("description", codecForString())
+ .property("description_i18n", codecForInternationalizedString())
+ .build("TalerExchangeApi.KycCheckPublicInformation");
export const codecForKycRequirementInformationId =
- (): Codec<KycRequirementInformationId> => codecForString() as Codec<KycRequirementInformationId>;
-
-export const codecForKycRequirementInformation = (): Codec<KycRequirementInformation> =>
- buildCodecForObject<KycRequirementInformation>()
- .property("form", codecForString())
- .property("description", codecForString())
- .property("description_i18n", codecForInternationalizedString())
- .property("id", codecOptional(codecForKycRequirementInformationId()))
- .build("TalerExchangeApi.KycRequirementInformation");
-
-export const codecForKycProcessClientInformation = (): Codec<KycProcessClientInformation> =>
- buildCodecForObject<KycProcessClientInformation>()
- .property("requirements", codecForList(codecForKycRequirementInformation()))
- .property("is_and_combinator", codecOptional(codecForBoolean()))
- .property("voluntary_checks", codecForMap(codecForKycCheckPublicInformation()))
- .build("TalerExchangeApi.KycProcessClientInformation");
+ (): Codec<KycRequirementInformationId> =>
+ codecForString() as Codec<KycRequirementInformationId>;
+
+export const codecForKycRequirementInformation =
+ (): Codec<KycRequirementInformation> =>
+ buildCodecForObject<KycRequirementInformation>()
+ .property("form", codecForString())
+ .property("description", codecForString())
+ .property("description_i18n", codecForInternationalizedString())
+ .property("id", codecOptional(codecForKycRequirementInformationId()))
+ .build("TalerExchangeApi.KycRequirementInformation");
+
+export const codecForKycProcessClientInformation =
+ (): Codec<KycProcessClientInformation> =>
+ buildCodecForObject<KycProcessClientInformation>()
+ .property(
+ "requirements",
+ codecForList(codecForKycRequirementInformation()),
+ )
+ .property("is_and_combinator", codecOptional(codecForBoolean()))
+ .property(
+ "voluntary_checks",
+ codecForMap(codecForKycCheckPublicInformation()),
+ )
+ .build("TalerExchangeApi.KycProcessClientInformation");
interface KycProcessStartInformation {
-
// URL to open.
redirect_url: string;
}
-export const codecForKycProcessStartInformation = (): Codec<KycProcessStartInformation> =>
- buildCodecForObject<KycProcessStartInformation>()
- .property("redirect_url", codecForURLString())
- .build("TalerExchangeApi.KycProcessStartInformation");
+export const codecForKycProcessStartInformation =
+ (): Codec<KycProcessStartInformation> =>
+ buildCodecForObject<KycProcessStartInformation>()
+ .property("redirect_url", codecForURLString())
+ .build("TalerExchangeApi.KycProcessStartInformation");
diff --git a/packages/taler-util/src/types-taler-wallet-transactions.ts b/packages/taler-util/src/types-taler-wallet-transactions.ts
index da3aaca2d..0a46071ca 100644
--- a/packages/taler-util/src/types-taler-wallet-transactions.ts
+++ b/packages/taler-util/src/types-taler-wallet-transactions.ts
@@ -127,7 +127,6 @@ export enum TransactionMinorState {
Unknown = "unknown",
Deposit = "deposit",
KycRequired = "kyc",
- AmlRequired = "aml",
MergeKycRequired = "merge-kyc",
Track = "track",
SubmitPayment = "submit-payment",
diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts
index a57b355a0..f135e7882 100644
--- a/packages/taler-util/src/types-taler-wallet.ts
+++ b/packages/taler-util/src/types-taler-wallet.ts
@@ -1445,6 +1445,18 @@ export enum ExchangeUpdateStatus {
OutdatedUpdate = "outdated-update",
}
+export enum ExchangeWalletKycStatus {
+ Done = "done",
+ /**
+ * Wallet needs to request KYC status.
+ */
+ LegiInit = "legi-init",
+ /**
+ * User requires KYC or AML.
+ */
+ Legi = "legi",
+}
+
export interface OperationErrorInfo {
error: TalerErrorDetail;
}
@@ -1466,6 +1478,9 @@ export interface ExchangeListItem {
exchangeUpdateStatus: ExchangeUpdateStatus;
ageRestrictionOptions: number[];
+ walletKycStatus?: ExchangeWalletKycStatus;
+ walletKycReservePub?: string;
+
/**
* P2P payments are disabled with this exchange
* (e.g. because no global fees are configured).
@@ -3583,3 +3598,34 @@ export type EmptyObject = Record<string, never>;
export const codecForEmptyObject = (): Codec<EmptyObject> =>
buildCodecForObject<EmptyObject>().build("EmptyObject");
+
+export interface TestingWaitWalletKycRequest {
+ exchangeBaseUrl: string;
+ amount: AmountString;
+ /**
+ * Do we wait for the KYC to be passed (true),
+ * or do we already return if legitimization is
+ * required (false).
+ */
+ passed: boolean;
+}
+
+export const codecForTestingWaitWalletKycRequest =
+ (): Codec<TestingWaitWalletKycRequest> =>
+ buildCodecForObject<TestingWaitWalletKycRequest>()
+ .property("exchangeBaseUrl", codecForString())
+ .property("amount", codecForAmountString())
+ .property("passed", codecForBoolean())
+ .build("TestingWaitWalletKycRequest");
+
+export interface StartExchangeWalletKycRequest {
+ exchangeBaseUrl: string;
+ amount: AmountString;
+}
+
+export const codecForStartExchangeWalletKycRequest =
+ (): Codec<StartExchangeWalletKycRequest> =>
+ buildCodecForObject<StartExchangeWalletKycRequest>()
+ .property("exchangeBaseUrl", codecForString())
+ .property("amount", codecForAmountString())
+ .build("StartExchangeWalletKycRequest");