taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 9c6d04fcbfa53330c79bd4ab2ad4729c20d6a09c
parent 86f045f6730bea2a02398326602efac9a81b1687
Author: Florian Dold <florian@dold.me>
Date:   Mon,  8 Jul 2024 15:17:19 +0200

util: more API type decl reorg

Diffstat:
Mpackages/taler-util/src/MerchantApiClient.ts | 49+++++++++----------------------------------------
Mpackages/taler-util/src/http-client/bank-core.ts | 1+
Mpackages/taler-util/src/http-client/bank-revenue.ts | 5++---
Mpackages/taler-util/src/http-client/exchange.ts | 10++++++----
Mpackages/taler-util/src/http-client/merchant.ts | 2++
Mpackages/taler-util/src/http-client/types.ts | 3551+------------------------------------------------------------------------------
Mpackages/taler-util/src/index.ts | 1-
Dpackages/taler-util/src/libeufin-api-types.ts | 31-------------------------------
Mpackages/taler-util/src/types-taler-common.ts | 6++++++
Mpackages/taler-util/src/types-taler-exchange.ts | 577++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mpackages/taler-util/src/types-taler-merchant.ts | 2653++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Apackages/taler-util/src/types-taler-revenue.ts | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 3308 insertions(+), 3673 deletions(-)

diff --git a/packages/taler-util/src/MerchantApiClient.ts b/packages/taler-util/src/MerchantApiClient.ts @@ -15,12 +15,7 @@ */ import { codecForAny } from "./codec.js"; -import { - TalerMerchantApi, - codecForMerchantConfig, - codecForMerchantOrderPrivateStatusResponse, - codecForPostOrderResponse, -} from "./http-client/types.js"; +import { TalerMerchantApi } from "./http-client/types.js"; import { HttpStatusCode } from "./http-status-codes.js"; import { createPlatformHttpLib, @@ -28,7 +23,6 @@ import { readSuccessResponseJsonOrThrow, readTalerErrorResponse, } from "./http.js"; -import { FacadeCredentials } from "./libeufin-api-types.js"; import { LibtoolVersion } from "./libtool-version.js"; import { Logger } from "./logging.js"; import { @@ -41,8 +35,15 @@ import { opSuccessFromHttp, opUnknownFailure, } from "./operation.js"; -import { AmountString } from "./types-taler-common.js"; import { TalerProtocolDuration } from "./time.js"; +import { AmountString } from "./types-taler-common.js"; +import { + FacadeCredentials, + OtpDeviceAddDetails, + codecForMerchantConfig, + codecForMerchantOrderPrivateStatusResponse, + codecForPostOrderResponse, +} from "./types-taler-merchant.js"; const logger = new Logger("MerchantApiClient.ts"); @@ -87,21 +88,6 @@ export interface DeleteTippingReserveArgs { purge?: boolean; } -interface MerchantBankAccount { - // The payto:// URI where the wallet will send coins. - payto_uri: string; - - // Optional base URL for a facade where the - // merchant backend can see incoming wire - // transfers to reconcile its accounting - // with that of the exchange. Used by - // taler-merchant-wirewatch. - credit_facade_url?: string; - - // Credentials for accessing the credit facade. - credit_facade_credentials?: FacadeCredentials; -} - export interface MerchantInstanceConfig { auth: MerchantAuthConfiguration; id: string; @@ -119,23 +105,6 @@ export interface PrivateOrderStatusQuery { sessionId?: string; } -export interface OtpDeviceAddDetails { - // Device ID to use. - otp_device_id: string; - - // Human-readable description for the device. - otp_device_description: string; - - // A base64-encoded key - otp_key: string; - - // Algorithm for computing the POS confirmation. - otp_algorithm: number; - - // Counter for counter-based OTP devices. - otp_ctr?: number; -} - /** * Client for the GNU Taler merchant backend. */ diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts @@ -18,6 +18,7 @@ import { AbsoluteTime, HttpStatusCode, LibtoolVersion, + LibtoolVersionString, LongPollParams, OperationAlternative, OperationFail, diff --git a/packages/taler-util/src/http-client/bank-revenue.ts b/packages/taler-util/src/http-client/bank-revenue.ts @@ -31,11 +31,10 @@ import { opUnknownFailure, } from "../operation.js"; import { - LongPollParams, - PaginationParams, codecForRevenueConfig, codecForRevenueIncomingHistory, -} from "./types.js"; +} from "../types-taler-revenue.js"; +import { LongPollParams, PaginationParams } from "./types.js"; import { addLongPollingParam, addPaginationParams } from "./utils.js"; export type TalerBankRevenueResultByMethod< diff --git a/packages/taler-util/src/http-client/exchange.ts b/packages/taler-util/src/http-client/exchange.ts @@ -24,14 +24,16 @@ import { timestampRoundedToBuffer, } from "../taler-crypto.js"; import { - OfficerAccount, - PaginationParams, - SigningKey, - TalerExchangeApi, codecForAmlDecisionDetails, codecForAmlRecords, codecForExchangeConfig, codecForExchangeKeys, +} from "../types-taler-exchange.js"; +import { + OfficerAccount, + PaginationParams, + SigningKey, + TalerExchangeApi, } from "./types.js"; import { CacheEvictor, addPaginationParams, nullEvictor } from "./utils.js"; diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts @@ -108,11 +108,13 @@ export enum TalerMerchantInstanceCacheEviction { DELETE_TOKENFAMILY, LAST, } + export enum TalerMerchantManagementCacheEviction { CREATE_INSTANCE = TalerMerchantInstanceCacheEviction.LAST + 1, UPDATE_INSTANCE, DELETE_INSTANCE, } + /** * Protocol version spoken with the core bank. * diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts @@ -1,58 +1,6 @@ -import { codecForAmountString } from "../amounts.js"; -import { - Codec, - buildCodecForObject, - buildCodecForUnion, - codecForAny, - codecForBoolean, - codecForConstNumber, - codecForConstString, - codecForEither, - codecForList, - codecForMap, - codecForNumber, - codecForString, - codecOptional, - codecOptionalDefault, -} from "../codec.js"; -import { PaytoString, codecForPaytoString } from "../payto.js"; -import { TalerUriString, codecForTalerUriString } from "../taleruri.js"; -import { - AbsoluteTime, - TalerProtocolDuration, - codecForDuration, - codecForTimestamp, -} from "../time.js"; -import { WithdrawalOperationStatus } from "../types-taler-bank-integration.js"; -import { - AmlOfficerPublicKeyP, - AmountString, - ClaimToken, - CoinPublicKey, - Cs25519Point, - CurrencySpecification, - DecimalNumber, - EddsaPublicKey, - HashCode, - ImageDataUrl, - Integer, - PaytoHash, - RelativeTime, - RsaPublicKey, - SafeUint64, - ShortHashCode, - Timestamp, - WireTransferIdentifierRawP, - codecForCurrencySpecificiation, - codecForDecimalNumber, - codecForInternationalizedString, - codecForURLString, -} from "../types-taler-common.js"; -import { - ExchangeWireAccount, - codecForExchangeWireAccount, -} from "../types-taler-exchange.js"; -import { codecForLocation } from "../types-taler-merchant.js"; +import { Codec, buildCodecForObject, codecForString } from "../codec.js"; +import { codecForTimestamp } from "../time.js"; +import { RelativeTime, Timestamp } from "../types-taler-common.js"; export type UserAndPassword = { username: string; @@ -218,3509 +166,22 @@ export const codecForTokenSuccessResponseMerchant = .property("expiration", codecForTimestamp) .build("TalerAuthentication.TokenSuccessResponseMerchant"); - //FIXME: implement this codec export const codecForURN = codecForString; -export const codecForExchangeConfigInfo = - (): Codec<TalerMerchantApi.ExchangeConfigInfo> => - buildCodecForObject<TalerMerchantApi.ExchangeConfigInfo>() - .property("base_url", codecForString()) - .property("currency", codecForString()) - .property("master_pub", codecForString()) - .build("TalerMerchantApi.ExchangeConfigInfo"); - -export const codecForMerchantConfig = - (): Codec<TalerMerchantApi.VersionResponse> => - buildCodecForObject<TalerMerchantApi.VersionResponse>() - .property("name", codecForConstString("taler-merchant")) - .property("currency", codecForString()) - .property("version", codecForString()) - .property("currencies", codecForMap(codecForCurrencySpecificiation())) - .property("exchanges", codecForList(codecForExchangeConfigInfo())) - .build("TalerMerchantApi.VersionResponse"); - -export const codecForClaimResponse = - (): Codec<TalerMerchantApi.ClaimResponse> => - buildCodecForObject<TalerMerchantApi.ClaimResponse>() - .property("contract_terms", codecForContractTerms()) - .property("sig", codecForString()) - .build("TalerMerchantApi.ClaimResponse"); - -export const codecForPaymentResponse = - (): Codec<TalerMerchantApi.PaymentResponse> => - buildCodecForObject<TalerMerchantApi.PaymentResponse>() - .property("pos_confirmation", codecOptional(codecForString())) - .property("sig", codecForString()) - .build("TalerMerchantApi.PaymentResponse"); - -export const codecForStatusPaid = (): Codec<TalerMerchantApi.StatusPaid> => - buildCodecForObject<TalerMerchantApi.StatusPaid>() - .property("refund_amount", codecForAmountString()) - .property("refund_pending", codecForBoolean()) - .property("refund_taken", codecForAmountString()) - .property("refunded", codecForBoolean()) - .property("type", codecForConstString("paid")) - .build("TalerMerchantApi.StatusPaid"); - -export const codecForStatusGoto = - (): Codec<TalerMerchantApi.StatusGotoResponse> => - buildCodecForObject<TalerMerchantApi.StatusGotoResponse>() - .property("public_reorder_url", codecForURLString()) - .property("type", codecForConstString("goto")) - .build("TalerMerchantApi.StatusGotoResponse"); - -export const codecForStatusStatusUnpaid = - (): Codec<TalerMerchantApi.StatusUnpaidResponse> => - buildCodecForObject<TalerMerchantApi.StatusUnpaidResponse>() - .property("type", codecForConstString("unpaid")) - .property("already_paid_order_id", codecOptional(codecForString())) - .property("fulfillment_url", codecOptional(codecForString())) - .property("taler_pay_uri", codecForTalerUriString()) - .build("TalerMerchantApi.PaymentResponse"); - -export const codecForPaidRefundStatusResponse = - (): Codec<TalerMerchantApi.PaidRefundStatusResponse> => - buildCodecForObject<TalerMerchantApi.PaidRefundStatusResponse>() - .property("pos_confirmation", codecOptional(codecForString())) - .property("refunded", codecForBoolean()) - .build("TalerMerchantApi.PaidRefundStatusResponse"); - -export const codecForMerchantAbortPayRefundSuccessStatus = - (): Codec<TalerMerchantApi.MerchantAbortPayRefundSuccessStatus> => - buildCodecForObject<TalerMerchantApi.MerchantAbortPayRefundSuccessStatus>() - .property("exchange_pub", codecForString()) - .property("exchange_sig", codecForString()) - .property("exchange_status", codecForConstNumber(200)) - .property("type", codecForConstString("success")) - .build("TalerMerchantApi.MerchantAbortPayRefundSuccessStatus"); - -export const codecForMerchantAbortPayRefundFailureStatus = - (): Codec<TalerMerchantApi.MerchantAbortPayRefundFailureStatus> => - buildCodecForObject<TalerMerchantApi.MerchantAbortPayRefundFailureStatus>() - .property("exchange_code", codecForNumber()) - .property("exchange_reply", codecForAny()) - .property("exchange_status", codecForNumber()) - .property("type", codecForConstString("failure")) - .build("TalerMerchantApi.MerchantAbortPayRefundFailureStatus"); - -export const codecForMerchantAbortPayRefundStatus = - (): Codec<TalerMerchantApi.MerchantAbortPayRefundStatus> => - buildCodecForUnion<TalerMerchantApi.MerchantAbortPayRefundStatus>() - .discriminateOn("type") - .alternative("success", codecForMerchantAbortPayRefundSuccessStatus()) - .alternative("failure", codecForMerchantAbortPayRefundFailureStatus()) - .build("TalerMerchantApi.MerchantAbortPayRefundStatus"); - -export const codecForAbortResponse = - (): Codec<TalerMerchantApi.AbortResponse> => - buildCodecForObject<TalerMerchantApi.AbortResponse>() - .property("refunds", codecForList(codecForMerchantAbortPayRefundStatus())) - .build("TalerMerchantApi.AbortResponse"); - -export const codecForWalletRefundResponse = - (): Codec<TalerMerchantApi.WalletRefundResponse> => - buildCodecForObject<TalerMerchantApi.WalletRefundResponse>() - .property("merchant_pub", codecForString()) - .property("refund_amount", codecForAmountString()) - .property("refunds", codecForList(codecForMerchantCoinRefundStatus())) - .build("TalerMerchantApi.AbortResponse"); - -export const codecForMerchantCoinRefundSuccessStatus = - (): Codec<TalerMerchantApi.MerchantCoinRefundSuccessStatus> => - buildCodecForObject<TalerMerchantApi.MerchantCoinRefundSuccessStatus>() - .property("type", codecForConstString("success")) - .property("coin_pub", codecForString()) - .property("exchange_status", codecForConstNumber(200)) - .property("exchange_sig", codecForString()) - .property("rtransaction_id", codecForNumber()) - .property("refund_amount", codecForAmountString()) - .property("exchange_pub", codecForString()) - .property("execution_time", codecForTimestamp) - .build("TalerMerchantApi.MerchantCoinRefundSuccessStatus"); - -export const codecForMerchantCoinRefundFailureStatus = - (): Codec<TalerMerchantApi.MerchantCoinRefundFailureStatus> => - buildCodecForObject<TalerMerchantApi.MerchantCoinRefundFailureStatus>() - .property("type", codecForConstString("failure")) - .property("coin_pub", codecForString()) - .property("exchange_status", codecForNumber()) - .property("rtransaction_id", codecForNumber()) - .property("refund_amount", codecForAmountString()) - .property("exchange_code", codecOptional(codecForNumber())) - .property("exchange_reply", codecOptional(codecForAny())) - .property("execution_time", codecForTimestamp) - .build("TalerMerchantApi.MerchantCoinRefundFailureStatus"); - -export const codecForMerchantCoinRefundStatus = - (): Codec<TalerMerchantApi.MerchantCoinRefundStatus> => - buildCodecForUnion<TalerMerchantApi.MerchantCoinRefundStatus>() - .discriminateOn("type") - .alternative("success", codecForMerchantCoinRefundSuccessStatus()) - .alternative("failure", codecForMerchantCoinRefundFailureStatus()) - .build("TalerMerchantApi.MerchantCoinRefundStatus"); - -export const codecForQueryInstancesResponse = - (): Codec<TalerMerchantApi.QueryInstancesResponse> => - buildCodecForObject<TalerMerchantApi.QueryInstancesResponse>() - .property("name", codecForString()) - .property("user_type", codecForString()) - .property("email", codecOptional(codecForString())) - .property("website", codecOptional(codecForString())) - .property("logo", codecOptional(codecForString())) - .property("merchant_pub", codecForString()) - .property("address", codecForLocation()) - .property("jurisdiction", codecForLocation()) - .property("use_stefan", codecForBoolean()) - .property("default_wire_transfer_delay", codecForDuration) - .property("default_pay_delay", codecForDuration) - .property( - "auth", - buildCodecForObject<{ - method: "external" | "token"; - }>() - .property( - "method", - codecForEither( - codecForConstString("token"), - codecForConstString("external"), - ), - ) - .build("TalerMerchantApi.QueryInstancesResponse.auth"), - ) - .build("TalerMerchantApi.QueryInstancesResponse"); - -export const codecForAccountKycRedirects = - (): Codec<TalerMerchantApi.AccountKycRedirects> => - buildCodecForObject<TalerMerchantApi.AccountKycRedirects>() - .property( - "pending_kycs", - codecForList(codecForMerchantAccountKycRedirect()), - ) - .property("timeout_kycs", codecForList(codecForExchangeKycTimeout())) - - .build("TalerMerchantApi.AccountKycRedirects"); - -export const codecForMerchantAccountKycRedirect = - (): Codec<TalerMerchantApi.MerchantAccountKycRedirect> => - buildCodecForObject<TalerMerchantApi.MerchantAccountKycRedirect>() - .property("kyc_url", codecForURLString()) - .property("aml_status", codecForNumber()) - .property("exchange_url", codecForURLString()) - .property("payto_uri", codecForPaytoString()) - .build("TalerMerchantApi.MerchantAccountKycRedirect"); - -export const codecForExchangeKycTimeout = - (): Codec<TalerMerchantApi.ExchangeKycTimeout> => - buildCodecForObject<TalerMerchantApi.ExchangeKycTimeout>() - .property("exchange_url", codecForURLString()) - .property("exchange_code", codecForNumber()) - .property("exchange_http_status", codecForNumber()) - .build("TalerMerchantApi.ExchangeKycTimeout"); - -export const codecForAccountAddResponse = - (): Codec<TalerMerchantApi.AccountAddResponse> => - buildCodecForObject<TalerMerchantApi.AccountAddResponse>() - .property("h_wire", codecForString()) - .property("salt", codecForString()) - .build("TalerMerchantApi.AccountAddResponse"); - -export const codecForAccountsSummaryResponse = - (): Codec<TalerMerchantApi.AccountsSummaryResponse> => - buildCodecForObject<TalerMerchantApi.AccountsSummaryResponse>() - .property("accounts", codecForList(codecForBankAccountEntry())) - .build("TalerMerchantApi.AccountsSummaryResponse"); - -export const codecForBankAccountEntry = - (): Codec<TalerMerchantApi.BankAccountEntry> => - buildCodecForObject<TalerMerchantApi.BankAccountEntry>() - .property("payto_uri", codecForPaytoString()) - .property("h_wire", codecForString()) - .property("active", codecOptional(codecForBoolean())) - .build("TalerMerchantApi.BankAccountEntry"); - -export const codecForBankAccountDetail = - (): Codec<TalerMerchantApi.BankAccountDetail> => - buildCodecForObject<TalerMerchantApi.BankAccountDetail>() - .property("payto_uri", codecForPaytoString()) - .property("h_wire", codecForString()) - .property("salt", codecForString()) - .property("credit_facade_url", codecOptional(codecForURLString())) - .property("active", codecOptional(codecForBoolean())) - .build("TalerMerchantApi.BankAccountEntry"); - -export const codecForInventorySummaryResponse = - (): Codec<TalerMerchantApi.InventorySummaryResponse> => - buildCodecForObject<TalerMerchantApi.InventorySummaryResponse>() - .property("products", codecForList(codecForInventoryEntry())) - .build("TalerMerchantApi.InventorySummaryResponse"); - -export const codecForInventoryEntry = - (): Codec<TalerMerchantApi.InventoryEntry> => - buildCodecForObject<TalerMerchantApi.InventoryEntry>() - .property("product_id", codecForString()) - .property("product_serial", codecForNumber()) - .build("TalerMerchantApi.InventoryEntry"); - -export const codecForMerchantPosProductDetail = - (): Codec<TalerMerchantApi.MerchantPosProductDetail> => - buildCodecForObject<TalerMerchantApi.MerchantPosProductDetail>() - .property("product_serial", codecForNumber()) - .property("product_id", codecOptional(codecForString())) - .property("categories", codecForList(codecForNumber())) - .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) - .property("unit", codecForString()) - .property("price", codecForAmountString()) - .property("image", codecForString()) - .property("taxes", codecOptional(codecForList(codecForTax()))) - .property("total_stock", codecForNumber()) - .property("minimum_age", codecOptional(codecForNumber())) - .build("TalerMerchantApi.MerchantPosProductDetail"); - -export const codecForMerchantCategory = - (): Codec<TalerMerchantApi.MerchantCategory> => - buildCodecForObject<TalerMerchantApi.MerchantCategory>() - .property("id", codecForNumber()) - .property("name", codecForString()) - .property("name_i18n", codecForInternationalizedString()) - .build("TalerMerchantApi.MerchantCategory"); - -export const codecForFullInventoryDetailsResponse = - (): Codec<TalerMerchantApi.FullInventoryDetailsResponse> => - buildCodecForObject<TalerMerchantApi.FullInventoryDetailsResponse>() - .property("categories", codecForList(codecForMerchantCategory())) - .property("products", codecForList(codecForMerchantPosProductDetail())) - .build("TalerMerchantApi.FullInventoryDetailsResponse"); - -export const codecForProductDetail = - (): Codec<TalerMerchantApi.ProductDetail> => - buildCodecForObject<TalerMerchantApi.ProductDetail>() - .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) - .property("unit", codecForString()) - .property("price", codecForAmountString()) - .property("image", codecForString()) - .property("taxes", codecOptional(codecForList(codecForTax()))) - .property("address", codecOptional(codecForLocation())) - .property("next_restock", codecOptional(codecForTimestamp)) - .property("total_stock", codecForNumber()) - .property("total_sold", codecForNumber()) - .property("total_lost", codecForNumber()) - .property("minimum_age", codecOptional(codecForNumber())) - .build("TalerMerchantApi.ProductDetail"); - -export const codecForTax = (): Codec<TalerMerchantApi.Tax> => - buildCodecForObject<TalerMerchantApi.Tax>() - .property("name", codecForString()) - .property("tax", codecForAmountString()) - .build("TalerMerchantApi.Tax"); - -export const codecForPostOrderResponse = - (): Codec<TalerMerchantApi.PostOrderResponse> => - buildCodecForObject<TalerMerchantApi.PostOrderResponse>() - .property("order_id", codecForString()) - .property("token", codecOptional(codecForString())) - .build("TalerMerchantApi.PostOrderResponse"); - -export const codecForOutOfStockResponse = - (): Codec<TalerMerchantApi.OutOfStockResponse> => - buildCodecForObject<TalerMerchantApi.OutOfStockResponse>() - .property("product_id", codecForString()) - .property("available_quantity", codecForNumber()) - .property("requested_quantity", codecForNumber()) - .property("restock_expected", codecForTimestamp) - .build("TalerMerchantApi.OutOfStockResponse"); - -export const codecForOrderHistory = (): Codec<TalerMerchantApi.OrderHistory> => - buildCodecForObject<TalerMerchantApi.OrderHistory>() - .property("orders", codecForList(codecForOrderHistoryEntry())) - .build("TalerMerchantApi.OrderHistory"); - -export const codecForOrderHistoryEntry = - (): Codec<TalerMerchantApi.OrderHistoryEntry> => - buildCodecForObject<TalerMerchantApi.OrderHistoryEntry>() - .property("order_id", codecForString()) - .property("row_id", codecForNumber()) - .property("timestamp", codecForTimestamp) - .property("amount", codecForAmountString()) - .property("summary", codecForString()) - .property("refundable", codecForBoolean()) - .property("paid", codecForBoolean()) - .build("TalerMerchantApi.OrderHistoryEntry"); - -export const codecForMerchant = (): Codec<TalerMerchantApi.Merchant> => - buildCodecForObject<TalerMerchantApi.Merchant>() - .property("name", codecForString()) - .property("email", codecOptional(codecForString())) - .property("logo", codecOptional(codecForString())) - .property("website", codecOptional(codecForString())) - .property("address", codecOptional(codecForLocation())) - .property("jurisdiction", codecOptional(codecForLocation())) - .build("TalerMerchantApi.MerchantInfo"); - -export const codecForExchange = (): Codec<TalerMerchantApi.Exchange> => - buildCodecForObject<TalerMerchantApi.Exchange>() - .property("master_pub", codecForString()) - .property("priority", codecForNumber()) - .property("url", codecForString()) - .build("TalerMerchantApi.Exchange"); - -export const codecForContractTerms = - (): Codec<TalerMerchantApi.ContractTerms> => - buildCodecForObject<TalerMerchantApi.ContractTerms>() - .property("order_id", codecForString()) - .property("fulfillment_url", codecOptional(codecForString())) - .property("fulfillment_message", codecOptional(codecForString())) - .property( - "fulfillment_message_i18n", - codecOptional(codecForInternationalizedString()), - ) - .property("merchant_base_url", codecForString()) - .property("h_wire", codecForString()) - .property("auto_refund", codecOptional(codecForDuration)) - .property("wire_method", codecForString()) - .property("summary", codecForString()) - .property( - "summary_i18n", - codecOptional(codecForInternationalizedString()), - ) - .property("nonce", codecForString()) - .property("amount", codecForAmountString()) - .property("pay_deadline", codecForTimestamp) - .property("refund_deadline", codecForTimestamp) - .property("wire_transfer_deadline", codecForTimestamp) - .property("timestamp", codecForTimestamp) - .property("delivery_location", codecOptional(codecForLocation())) - .property("delivery_date", codecOptional(codecForTimestamp)) - .property("max_fee", codecForAmountString()) - .property("merchant", codecForMerchant()) - .property("merchant_pub", codecForString()) - .property("exchanges", codecForList(codecForExchange())) - .property("products", codecForList(codecForProduct())) - .property("extra", codecForAny()) - .build("TalerMerchantApi.ContractTerms"); - -export const codecForProduct = (): Codec<TalerMerchantApi.Product> => - buildCodecForObject<TalerMerchantApi.Product>() - .property("product_id", codecOptional(codecForString())) - .property("description", codecForString()) - .property( - "description_i18n", - codecOptional(codecForInternationalizedString()), - ) - .property("quantity", codecOptional(codecForNumber())) - .property("unit", codecOptional(codecForString())) - .property("price", codecOptional(codecForAmountString())) - .property("image", codecOptional(codecForString())) - .property("taxes", codecOptional(codecForList(codecForTax()))) - .property("delivery_date", codecOptional(codecForTimestamp)) - .build("TalerMerchantApi.Product"); - -export const codecForCheckPaymentPaidResponse = - (): Codec<TalerMerchantApi.CheckPaymentPaidResponse> => - buildCodecForObject<TalerMerchantApi.CheckPaymentPaidResponse>() - .property("order_status", codecForConstString("paid")) - .property("refunded", codecForBoolean()) - .property("refund_pending", codecForBoolean()) - .property("wired", codecForBoolean()) - .property("deposit_total", codecForAmountString()) - .property("exchange_code", codecForNumber()) - .property("exchange_http_status", codecForNumber()) - .property("refund_amount", codecForAmountString()) - .property("contract_terms", codecForContractTerms()) - .property("wire_reports", codecForList(codecForTransactionWireReport())) - .property("wire_details", codecForList(codecForTransactionWireTransfer())) - .property("refund_details", codecForList(codecForRefundDetails())) - .property("order_status_url", codecForURLString()) - .build("TalerMerchantApi.CheckPaymentPaidResponse"); - -export const codecForCheckPaymentUnpaidResponse = - (): Codec<TalerMerchantApi.CheckPaymentUnpaidResponse> => - buildCodecForObject<TalerMerchantApi.CheckPaymentUnpaidResponse>() - .property("order_status", codecForConstString("unpaid")) - .property("taler_pay_uri", codecForTalerUriString()) - .property("creation_time", codecForTimestamp) - .property("summary", codecForString()) - .property("total_amount", codecForAmountString()) - .property("already_paid_order_id", codecOptional(codecForString())) - .property("already_paid_fulfillment_url", codecOptional(codecForString())) - .property("order_status_url", codecForString()) - .build("TalerMerchantApi.CheckPaymentPaidResponse"); - -export const codecForCheckPaymentClaimedResponse = - (): Codec<TalerMerchantApi.CheckPaymentClaimedResponse> => - buildCodecForObject<TalerMerchantApi.CheckPaymentClaimedResponse>() - .property("order_status", codecForConstString("claimed")) - .property("contract_terms", codecForContractTerms()) - .build("TalerMerchantApi.CheckPaymentClaimedResponse"); - -export const codecForMerchantOrderPrivateStatusResponse = - (): Codec<TalerMerchantApi.MerchantOrderStatusResponse> => - buildCodecForUnion<TalerMerchantApi.MerchantOrderStatusResponse>() - .discriminateOn("order_status") - .alternative("paid", codecForCheckPaymentPaidResponse()) - .alternative("unpaid", codecForCheckPaymentUnpaidResponse()) - .alternative("claimed", codecForCheckPaymentClaimedResponse()) - .build("TalerMerchantApi.MerchantOrderStatusResponse"); - -export const codecForRefundDetails = - (): Codec<TalerMerchantApi.RefundDetails> => - buildCodecForObject<TalerMerchantApi.RefundDetails>() - .property("reason", codecForString()) - .property("pending", codecForBoolean()) - .property("timestamp", codecForTimestamp) - .property("amount", codecForAmountString()) - .build("TalerMerchantApi.RefundDetails"); - -export const codecForTransactionWireTransfer = - (): Codec<TalerMerchantApi.TransactionWireTransfer> => - buildCodecForObject<TalerMerchantApi.TransactionWireTransfer>() - .property("exchange_url", codecForURLString()) - .property("wtid", codecForString()) - .property("execution_time", codecForTimestamp) - .property("amount", codecForAmountString()) - .property("confirmed", codecForBoolean()) - .build("TalerMerchantApi.TransactionWireTransfer"); - -export const codecForTransactionWireReport = - (): Codec<TalerMerchantApi.TransactionWireReport> => - buildCodecForObject<TalerMerchantApi.TransactionWireReport>() - .property("code", codecForNumber()) - .property("hint", codecForString()) - .property("exchange_code", codecForNumber()) - .property("exchange_http_status", codecForNumber()) - .property("coin_pub", codecForString()) - .build("TalerMerchantApi.TransactionWireReport"); - -export const codecForMerchantRefundResponse = - (): Codec<TalerMerchantApi.MerchantRefundResponse> => - buildCodecForObject<TalerMerchantApi.MerchantRefundResponse>() - .property("taler_refund_uri", codecForTalerUriString()) - .property("h_contract", codecForString()) - .build("TalerMerchantApi.MerchantRefundResponse"); - -export const codecForTansferList = (): Codec<TalerMerchantApi.TransferList> => - buildCodecForObject<TalerMerchantApi.TransferList>() - .property("transfers", codecForList(codecForTransferDetails())) - .build("TalerMerchantApi.TransferList"); - -export const codecForTransferDetails = - (): Codec<TalerMerchantApi.TransferDetails> => - buildCodecForObject<TalerMerchantApi.TransferDetails>() - .property("credit_amount", codecForAmountString()) - .property("wtid", codecForString()) - .property("payto_uri", codecForPaytoString()) - .property("exchange_url", codecForURLString()) - .property("transfer_serial_id", codecForNumber()) - .property("execution_time", codecOptional(codecForTimestamp)) - .property("verified", codecOptional(codecForBoolean())) - .property("confirmed", codecOptional(codecForBoolean())) - .build("TalerMerchantApi.TransferDetails"); - -export const codecForOtpDeviceSummaryResponse = - (): Codec<TalerMerchantApi.OtpDeviceSummaryResponse> => - buildCodecForObject<TalerMerchantApi.OtpDeviceSummaryResponse>() - .property("otp_devices", codecForList(codecForOtpDeviceEntry())) - .build("TalerMerchantApi.OtpDeviceSummaryResponse"); - -export const codecForOtpDeviceEntry = - (): Codec<TalerMerchantApi.OtpDeviceEntry> => - buildCodecForObject<TalerMerchantApi.OtpDeviceEntry>() - .property("otp_device_id", codecForString()) - .property("device_description", codecForString()) - .build("TalerMerchantApi.OtpDeviceEntry"); - -export const codecForOtpDeviceDetails = - (): Codec<TalerMerchantApi.OtpDeviceDetails> => - buildCodecForObject<TalerMerchantApi.OtpDeviceDetails>() - .property("device_description", codecForString()) - .property("otp_algorithm", codecForNumber()) - .property("otp_ctr", codecOptional(codecForNumber())) - .property("otp_timestamp", codecForNumber()) - .property("otp_code", codecOptional(codecForString())) - .build("TalerMerchantApi.OtpDeviceDetails"); - -export const codecForTemplateSummaryResponse = - (): Codec<TalerMerchantApi.TemplateSummaryResponse> => - buildCodecForObject<TalerMerchantApi.TemplateSummaryResponse>() - .property("templates", codecForList(codecForTemplateEntry())) - .build("TalerMerchantApi.TemplateSummaryResponse"); - -export const codecForTemplateEntry = - (): Codec<TalerMerchantApi.TemplateEntry> => - buildCodecForObject<TalerMerchantApi.TemplateEntry>() - .property("template_id", codecForString()) - .property("template_description", codecForString()) - .build("TalerMerchantApi.TemplateEntry"); - -export const codecForTemplateDetails = - (): Codec<TalerMerchantApi.TemplateDetails> => - buildCodecForObject<TalerMerchantApi.TemplateDetails>() - .property("template_description", codecForString()) - .property("otp_id", codecOptional(codecForString())) - .property("template_contract", codecForTemplateContractDetails()) - .property( - "editable_defaults", - codecOptional(codecForTemplateContractDetailsDefaults()), - ) - .build("TalerMerchantApi.TemplateDetails"); - -export const codecForTemplateContractDetails = - (): Codec<TalerMerchantApi.TemplateContractDetails> => - buildCodecForObject<TalerMerchantApi.TemplateContractDetails>() - .property("summary", codecOptional(codecForString())) - .property("currency", codecOptional(codecForString())) - .property("amount", codecOptional(codecForAmountString())) - .property("minimum_age", codecForNumber()) - .property("pay_duration", codecForDuration) - .build("TalerMerchantApi.TemplateContractDetails"); - -export const codecForTemplateContractDetailsDefaults = - (): Codec<TalerMerchantApi.TemplateContractDetailsDefaults> => - buildCodecForObject<TalerMerchantApi.TemplateContractDetailsDefaults>() - .property("summary", codecOptional(codecForString())) - .property("currency", codecOptional(codecForString())) - .property("amount", codecOptional(codecForAmountString())) - .build("TalerMerchantApi.TemplateContractDetailsDefaults"); - -export const codecForWalletTemplateDetails = - (): Codec<TalerMerchantApi.WalletTemplateDetails> => - buildCodecForObject<TalerMerchantApi.WalletTemplateDetails>() - .property("template_contract", codecForTemplateContractDetails()) - .property( - "editable_defaults", - codecOptional(codecForTemplateContractDetailsDefaults()), - ) - .build("TalerMerchantApi.WalletTemplateDetails"); - -export const codecForWebhookSummaryResponse = - (): Codec<TalerMerchantApi.WebhookSummaryResponse> => - buildCodecForObject<TalerMerchantApi.WebhookSummaryResponse>() - .property("webhooks", codecForList(codecForWebhookEntry())) - .build("TalerMerchantApi.WebhookSummaryResponse"); - -export const codecForWebhookEntry = (): Codec<TalerMerchantApi.WebhookEntry> => - buildCodecForObject<TalerMerchantApi.WebhookEntry>() - .property("webhook_id", codecForString()) - .property("event_type", codecForString()) - .build("TalerMerchantApi.WebhookEntry"); - -export const codecForWebhookDetails = - (): Codec<TalerMerchantApi.WebhookDetails> => - buildCodecForObject<TalerMerchantApi.WebhookDetails>() - .property("event_type", codecForString()) - .property("url", codecForString()) - .property("http_method", codecForString()) - .property("header_template", codecOptional(codecForString())) - .property("body_template", codecOptional(codecForString())) - .build("TalerMerchantApi.WebhookDetails"); - -export const codecForTokenFamilyKind = - (): Codec<TalerMerchantApi.TokenFamilyKind> => - codecForEither( - codecForConstString("discount"), - codecForConstString("subscription"), - ) as any; //FIXME: create a codecForEnum -export const codecForTokenFamilyDetails = - (): Codec<TalerMerchantApi.TokenFamilyDetails> => - buildCodecForObject<TalerMerchantApi.TokenFamilyDetails>() - .property("slug", codecForString()) - .property("name", codecForString()) - .property("description", codecForString()) - .property("description_i18n", codecForInternationalizedString()) - .property("valid_after", codecForTimestamp) - .property("valid_before", codecForTimestamp) - .property("duration", codecForDuration) - .property("kind", codecForTokenFamilyKind()) - .property("issued", codecForNumber()) - .property("redeemed", codecForNumber()) - .build("TalerMerchantApi.TokenFamilyDetails"); - -export const codecForTokenFamiliesList = - (): Codec<TalerMerchantApi.TokenFamiliesList> => - buildCodecForObject<TalerMerchantApi.TokenFamiliesList>() - .property("token_families", codecForList(codecForTokenFamilySummary())) - .build("TalerMerchantApi.TokenFamiliesList"); - -export const codecForTokenFamilySummary = - (): Codec<TalerMerchantApi.TokenFamilySummary> => - buildCodecForObject<TalerMerchantApi.TokenFamilySummary>() - .property("slug", codecForString()) - .property("name", codecForString()) - .property("valid_after", codecForTimestamp) - .property("valid_before", codecForTimestamp) - .property("kind", codecForTokenFamilyKind()) - .build("TalerMerchantApi.TokenFamilySummary"); - -export const codecForInstancesResponse = - (): Codec<TalerMerchantApi.InstancesResponse> => - buildCodecForObject<TalerMerchantApi.InstancesResponse>() - .property("instances", codecForList(codecForInstance())) - .build("TalerMerchantApi.InstancesResponse"); - -export const codecForInstance = (): Codec<TalerMerchantApi.Instance> => - buildCodecForObject<TalerMerchantApi.Instance>() - .property("name", codecForString()) - .property("user_type", codecForString()) - .property("website", codecOptional(codecForString())) - .property("logo", codecOptional(codecForString())) - .property("id", codecForString()) - .property("merchant_pub", codecForString()) - .property("payment_targets", codecForList(codecForString())) - .property("deleted", codecForBoolean()) - .build("TalerMerchantApi.Instance"); - -export const codecForExchangeConfig = - (): Codec<TalerExchangeApi.ExchangeVersionResponse> => - buildCodecForObject<TalerExchangeApi.ExchangeVersionResponse>() - .property("version", codecForString()) - .property("name", codecForConstString("taler-exchange")) - .property("implementation", codecOptional(codecForURN())) - .property("currency", codecForString()) - .property("currency_specification", codecForCurrencySpecificiation()) - .property("supported_kyc_requirements", codecForList(codecForString())) - .build("TalerExchangeApi.ExchangeVersionResponse"); - -export const codecForExchangeKeys = - (): Codec<TalerExchangeApi.ExchangeKeysResponse> => - buildCodecForObject<TalerExchangeApi.ExchangeKeysResponse>() - .property("version", codecForString()) - .property("base_url", codecForString()) - .property("currency", codecForString()) - .build("TalerExchangeApi.ExchangeKeysResponse"); - -export const codecForRevenueConfig = (): Codec<TalerRevenueApi.RevenueConfig> => - buildCodecForObject<TalerRevenueApi.RevenueConfig>() - .property("name", codecForConstString("taler-revenue")) - .property("version", codecForString()) - .property("currency", codecForString()) - .property("implementation", codecOptional(codecForString())) - .build("TalerRevenueApi.RevenueConfig"); - -export const codecForRevenueIncomingHistory = - (): Codec<TalerRevenueApi.RevenueIncomingHistory> => - buildCodecForObject<TalerRevenueApi.RevenueIncomingHistory>() - .property("credit_account", codecForPaytoString()) - .property( - "incoming_transactions", - codecForList(codecForRevenueIncomingBankTransaction()), - ) - .build("TalerRevenueApi.MerchantIncomingHistory"); - -export const codecForRevenueIncomingBankTransaction = - (): Codec<TalerRevenueApi.RevenueIncomingBankTransaction> => - buildCodecForObject<TalerRevenueApi.RevenueIncomingBankTransaction>() - .property("amount", codecForAmountString()) - .property("date", codecForTimestamp) - .property("debit_account", codecForPaytoString()) - .property("row_id", codecForNumber()) - .property("subject", codecForString()) - .build("TalerRevenueApi.RevenueIncomingBankTransaction"); - -export const codecForAmlRecords = (): Codec<TalerExchangeApi.AmlRecords> => - buildCodecForObject<TalerExchangeApi.AmlRecords>() - .property("records", codecForList(codecForAmlRecord())) - .build("TalerExchangeApi.AmlRecords"); - -export const codecForAmlRecord = (): Codec<TalerExchangeApi.AmlRecord> => - buildCodecForObject<TalerExchangeApi.AmlRecord>() - .property("current_state", codecForNumber()) - .property("h_payto", codecForString()) - .property("rowid", codecForNumber()) - .property("threshold", codecForAmountString()) - .build("TalerExchangeApi.AmlRecord"); - -export const codecForAmlDecisionDetails = - (): Codec<TalerExchangeApi.AmlDecisionDetails> => - buildCodecForObject<TalerExchangeApi.AmlDecisionDetails>() - .property("aml_history", codecForList(codecForAmlDecisionDetail())) - .property("kyc_attributes", codecForList(codecForKycDetail())) - .build("TalerExchangeApi.AmlDecisionDetails"); - -export const codecForAmlDecisionDetail = - (): Codec<TalerExchangeApi.AmlDecisionDetail> => - buildCodecForObject<TalerExchangeApi.AmlDecisionDetail>() - .property("justification", codecForString()) - .property("new_state", codecForNumber()) - .property("decision_time", codecForTimestamp) - .property("new_threshold", codecForAmountString()) - .property("decider_pub", codecForString()) - .build("TalerExchangeApi.AmlDecisionDetail"); - -interface KycDetail { - provider_section: string; - attributes?: Object; - collection_time: Timestamp; - expiration_time: Timestamp; -} -export const codecForKycDetail = (): Codec<TalerExchangeApi.KycDetail> => - buildCodecForObject<TalerExchangeApi.KycDetail>() - .property("provider_section", codecForString()) - .property("attributes", codecOptional(codecForAny())) - .property("collection_time", codecForTimestamp) - .property("expiration_time", codecForTimestamp) - .build("TalerExchangeApi.KycDetail"); - -export const codecForAmlDecision = (): Codec<TalerExchangeApi.AmlDecision> => - buildCodecForObject<TalerExchangeApi.AmlDecision>() - .property("justification", codecForString()) - .property("new_threshold", codecForAmountString()) - .property("h_payto", codecForString()) - .property("new_state", codecForNumber()) - .property("officer_sig", codecForString()) - .property("decision_time", codecForTimestamp) - .property("kyc_requirements", codecOptional(codecForList(codecForString()))) - .build("TalerExchangeApi.AmlDecision"); - -export const codecForTemplateEditableDetails = - (): Codec<TalerMerchantApi.TemplateEditableDetails> => - buildCodecForObject<TalerMerchantApi.TemplateEditableDetails>() - .property("summary", codecOptional(codecForString())) - .property("currency", codecOptional(codecForString())) - .property("amount", codecOptional(codecForAmountString())) - .build("TemplateEditableDetails"); - -export const codecForMerchantReserveCreateConfirmation = - (): Codec<TalerMerchantApi.MerchantReserveCreateConfirmation> => - buildCodecForObject<TalerMerchantApi.MerchantReserveCreateConfirmation>() - .property("accounts", codecForList(codecForExchangeWireAccount())) - .property("reserve_pub", codecForString()) - .build("MerchantReserveCreateConfirmation"); - -type EddsaSignature = string; -// base32 encoded RSA blinded signature. -type BlindedRsaSignature = string; -type Base32 = string; - -type RsaSignature = string; -type Float = number; -type LibtoolVersion = string; -// The type of a coin's blinded envelope depends on the cipher that is used -// for signing with a denomination key. -type CoinEnvelope = RSACoinEnvelope | CSCoinEnvelope; -// For denomination signatures based on RSA, the planchet is just a blinded -// coin's public EdDSA key. -interface RSACoinEnvelope { - cipher: "RSA" | "RSA+age_restricted"; - rsa_blinded_planchet: string; // Crockford Base32 encoded -} -// For denomination signatures based on Blind Clause-Schnorr, the planchet -// consists of the public nonce and two Curve25519 scalars which are two -// blinded challenges in the Blinded Clause-Schnorr signature scheme. -// See https://taler.net/papers/cs-thesis.pdf for details. -interface CSCoinEnvelope { - cipher: "CS" | "CS+age_restricted"; - cs_nonce: string; // Crockford Base32 encoded - cs_blinded_c0: string; // Crockford Base32 encoded - cs_blinded_c1: string; // Crockford Base32 encoded -} -// Secret for blinding/unblinding. -// An RSA blinding secret, which is basically -// a 256-bit nonce, converted to Crockford Base32. -type DenominationBlindingKeyP = string; - export * as TalerWireGatewayApi from "../types-taler-wire-gateway.js"; -export namespace TalerRevenueApi { - export interface RevenueConfig { - // Name of the API. - name: "taler-revenue"; - - // libtool-style representation of the Bank protocol version, see - // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning - // The format is "current:revision:age". - version: string; - - // Currency used by this gateway. - currency: string; - - // URN of the implementation (needed to interpret 'revision' in version). - // @since v0, may become mandatory in the future. - implementation?: string; - } - - export interface RevenueIncomingHistory { - // Array of incoming transactions. - incoming_transactions: RevenueIncomingBankTransaction[]; - - // Payto URI to identify the receiver of funds. - // Credit account is shared by all incoming transactions - // as per the nature of the request. - credit_account: string; - } - - export interface RevenueIncomingBankTransaction { - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Date of the transaction. - date: Timestamp; - - // Amount transferred. - amount: AmountString; - - // Payto URI to identify the sender of funds. - debit_account: string; - - // The wire transfer subject. - subject: string; - } -} - export * as TalerBankIntegrationApi from "../types-taler-bank-integration.js"; export * as TalerBankConversionApi from "../types-taler-bank-conversion.js"; export * as TalerCorebankApi from "../types-taler-corebank.js"; -export namespace TalerExchangeApi { - export enum AmlState { - normal = 0, - pending = 1, - frozen = 2, - } - - export interface AmlRecords { - // Array of AML records matching the query. - records: AmlRecord[]; - } - export interface AmlRecord { - // Which payto-address is this record about. - // Identifies a GNU Taler wallet or an affected bank account. - h_payto: PaytoHash; - - // What is the current AML state. - current_state: AmlState; - - // Monthly transaction threshold before a review will be triggered - threshold: AmountString; - - // RowID of the record. - rowid: Integer; - } - - export interface AmlDecisionDetails { - // Array of AML decisions made for this account. Possibly - // contains only the most recent decision if "history" was - // not set to 'true'. - aml_history: AmlDecisionDetail[]; - - // Array of KYC attributes obtained for this account. - kyc_attributes: KycDetail[]; - } - export interface AmlDecisionDetail { - // What was the justification given? - justification: string; - - // What is the new AML state. - new_state: Integer; - - // When was this decision made? - decision_time: Timestamp; - - // What is the new AML decision threshold (in monthly transaction volume)? - new_threshold: AmountString; - - // 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 - provider_section: string; - - // The collected KYC data. NULL if the attribute data could not - // be decrypted (internal error of the exchange, likely the - // attribute key was changed). - attributes?: Object; - - // Time when the KYC data was collected - collection_time: Timestamp; - - // Time when the validity of the KYC data will expire - expiration_time: Timestamp; - } - - export interface AmlDecision { - // Human-readable justification for the decision. - justification: string; - - // At what monthly transaction volume should the - // decision be automatically reviewed? - new_threshold: AmountString; - - // Which payto-address is the decision about? - // Identifies a GNU Taler wallet or an affected bank account. - h_payto: PaytoHash; - - // What is the new AML state (e.g. frozen, unfrozen, etc.) - // Numerical values are defined in AmlDecisionState. - new_state: Integer; - - // Signature by the AML officer over a - // TALER_MasterAmlOfficerStatusPS. - // Must have purpose TALER_SIGNATURE_MASTER_AML_KEY. - officer_sig: EddsaSignature; - - // When was the decision made? - decision_time: Timestamp; - - // Optional argument to impose new KYC requirements - // that the customer has to satisfy to unblock transactions. - kyc_requirements?: string[]; - } - - export interface ExchangeVersionResponse { - // libtool-style representation of the Exchange protocol version, see - // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning - // The format is "current:revision:age". - version: string; - - // Name of the protocol. - name: "taler-exchange"; - - // URN of the implementation (needed to interpret 'revision' in version). - // @since v18, may become mandatory in the future. - implementation?: string; - - // Currency supported by this exchange, given - // as a currency code ("USD" or "EUR"). - currency: string; - - // How wallets should render this currency. - currency_specification: CurrencySpecification; - - // Names of supported KYC requirements. - supported_kyc_requirements: string[]; - } - - export type AccountRestriction = - | RegexAccountRestriction - | DenyAllAccountRestriction; - // Account restriction that disables this type of - // account for the indicated operation categorically. - export interface DenyAllAccountRestriction { - type: "deny"; - } - // Accounts interacting with this type of account - // restriction must have a payto://-URI matching - // the given regex. - export interface RegexAccountRestriction { - type: "regex"; - - // Regular expression that the payto://-URI of the - // partner account must follow. The regular expression - // should follow posix-egrep, but without support for character - // classes, GNU extensions, back-references or intervals. See - // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html - // for a description of the posix-egrep syntax. Applications - // may support regexes with additional features, but exchanges - // must not use such regexes. - payto_regex: string; - - // Hint for a human to understand the restriction - // (that is hopefully easier to comprehend than the regex itself). - human_hint: string; - - // Map from IETF BCP 47 language tags to localized - // human hints. - human_hint_i18n?: { [lang_tag: string]: string }; - } - - export interface WireAccount { - // payto:// URI identifying the account and wire method - payto_uri: PaytoString; - - // URI to convert amounts from or to the currency used by - // this wire account of the exchange. Missing if no - // conversion is applicable. - conversion_url?: string; - - // Restrictions that apply to bank accounts that would send - // funds to the exchange (crediting this exchange bank account). - // Optional, empty array for unrestricted. - credit_restrictions: AccountRestriction[]; - - // Restrictions that apply to bank accounts that would receive - // funds from the exchange (debiting this exchange bank account). - // Optional, empty array for unrestricted. - debit_restrictions: AccountRestriction[]; - - // Signature using the exchange's offline key over - // a TALER_MasterWireDetailsPS - // with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS. - master_sig: EddsaSignature; - } - - export interface ExchangeKeysResponse { - // libtool-style representation of the Exchange protocol version, see - // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning - // The format is "current:revision:age". - version: string; - - // The exchange's base URL. - base_url: string; - - // The exchange's currency or asset unit. - currency: string; - - /** - * FIXME: PARTIALLY IMPLEMENTED!! - */ - - // How wallets should render this currency. - // currency_specification: CurrencySpecification; - - // // Absolute cost offset for the STEFAN curve used - // // to (over) approximate fees payable by amount. - // stefan_abs: AmountString; - - // // Factor to multiply the logarithm of the amount - // // with to (over) approximate fees payable by amount. - // // Note that the total to be paid is first to be - // // divided by the smallest denomination to obtain - // // the value that the logarithm is to be taken of. - // stefan_log: AmountString; - - // // Linear cost factor for the STEFAN curve used - // // to (over) approximate fees payable by amount. - // // - // // Note that this is a scalar, as it is multiplied - // // with the actual amount. - // stefan_lin: Float; - - // // Type of the asset. "fiat", "crypto", "regional" - // // or "stock". Wallets should adjust their UI/UX - // // based on this value. - // asset_type: string; - - // // Array of wire accounts operated by the exchange for - // // incoming wire transfers. - // accounts: WireAccount[]; - - // // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") - // // to wire fees. - // wire_fees: { method: AggregateTransferFee[] }; - - // // List of exchanges that this exchange is partnering - // // with to enable wallet-to-wallet transfers. - // wads: ExchangePartner[]; - - // // Set to true if this exchange allows the use - // // of reserves for rewards. - // // @deprecated in protocol v18. - // rewards_allowed: false; - - // // EdDSA master public key of the exchange, used to sign entries - // // in denoms and signkeys. - // master_public_key: EddsaPublicKey; - - // // Relative duration until inactive reserves are closed; - // // not signed (!), can change without notice. - // 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. - // // Currency must match currency. - // wallet_balance_limit_without_kyc?: AmountString[]; - - // // Denominations offered by this exchange - // denominations: DenomGroup[]; - - // // Compact EdDSA signature (binary-only) over the - // // contatentation of all of the master_sigs (in reverse - // // chronological order by group) in the arrays under - // // "denominations". Signature of TALER_ExchangeKeySetPS - // exchange_sig: EddsaSignature; - - // // Public EdDSA key of the exchange that was used to generate the signature. - // // Should match one of the exchange's signing keys from signkeys. It is given - // // explicitly as the client might otherwise be confused by clock skew as to - // // which signing key was used for the exchange_sig. - // exchange_pub: EddsaPublicKey; - - // // Denominations for which the exchange currently offers/requests recoup. - // recoup: Recoup[]; - - // // Array of globally applicable fees by time range. - // global_fees: GlobalFees[]; - - // // The date when the denomination keys were last updated. - // list_issue_date: Timestamp; - - // // Auditors of the exchange. - // auditors: AuditorKeys[]; - - // // The exchange's signing keys. - // signkeys: SignKey[]; - - // // Optional field with a dictionary of (name, object) pairs defining the - // // supported and enabled extensions, such as age_restriction. - // extensions?: { name: ExtensionManifest }; - - // // Signature by the exchange master key of the SHA-256 hash of the - // // normalized JSON-object of field extensions, if it was set. - // // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. - // extensions_sig?: EddsaSignature; - } - - interface ExtensionManifest { - // The criticality of the extension MUST be provided. It has the same - // semantics as "critical" has for extensions in X.509: - // - if "true", the client must "understand" the extension before - // proceeding, - // - if "false", clients can safely skip extensions they do not - // understand. - // (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2) - critical: boolean; - - // The version information MUST be provided in Taler's protocol version - // ranges notation, see - // https://docs.taler.net/core/api-common.html#protocol-version-ranges - version: LibtoolVersion; - - // Optional configuration object, defined by the feature itself - config?: object; - } - - interface SignKey { - // The actual exchange's EdDSA signing public key. - key: EddsaPublicKey; - - // Initial validity date for the signing key. - stamp_start: Timestamp; - - // Date when the exchange will stop using the signing key, allowed to overlap - // slightly with the next signing key's validity to allow for clock skew. - stamp_expire: Timestamp; - - // Date when all signatures made by the signing key expire and should - // henceforth no longer be considered valid in legal disputes. - stamp_end: Timestamp; - - // Signature over key and stamp_expire by the exchange master key. - // Signature of TALER_ExchangeSigningKeyValidityPS. - // Must have purpose TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY. - master_sig: EddsaSignature; - } - - interface AuditorKeys { - // The auditor's EdDSA signing public key. - auditor_pub: EddsaPublicKey; - - // The auditor's URL. - auditor_url: string; - - // The auditor's name (for humans). - auditor_name: string; - - // An array of denomination keys the auditor affirms with its signature. - // Note that the message only includes the hash of the public key, while the - // signature is actually over the expanded information including expiration - // times and fees. The exact format is described below. - denomination_keys: AuditorDenominationKey[]; - } - interface AuditorDenominationKey { - // Hash of the public RSA key used to sign coins of the respective - // denomination. Note that the auditor's signature covers more than just - // the hash, but this other information is already provided in denoms and - // thus not repeated here. - denom_pub_h: HashCode; - - // Signature of TALER_ExchangeKeyValidityPS. - auditor_sig: EddsaSignature; - } - - interface GlobalFees { - // What date (inclusive) does these fees go into effect? - start_date: Timestamp; +export * as TalerExchangeApi from "../types-taler-exchange.js"; - // What date (exclusive) does this fees stop going into effect? - end_date: Timestamp; +export * as TalerRevenueApi from "../types-taler-revenue.js"; - // Account history fee, charged when a user wants to - // obtain a reserve/account history. - history_fee: AmountString; - - // Annual fee charged for having an open account at the - // exchange. Charged to the account. If the account - // balance is insufficient to cover this fee, the account - // is automatically deleted/closed. (Note that the exchange - // will keep the account history around for longer for - // regulatory reasons.) - account_fee: AmountString; - - // Purse fee, charged only if a purse is abandoned - // and was not covered by the account limit. - purse_fee: AmountString; - - // How long will the exchange preserve the account history? - // After an account was deleted/closed, the exchange will - // retain the account history for legal reasons until this time. - history_expiration: RelativeTime; - - // Non-negative number of concurrent purses that any - // account holder is allowed to create without having - // to pay the purse_fee. - purse_account_limit: Integer; - - // How long does an exchange keep a purse around after a purse - // has expired (or been successfully merged)? A 'GET' request - // for a purse will succeed until the purse expiration time - // plus this value. - purse_timeout: RelativeTime; - - // Signature of TALER_GlobalFeesPS. - master_sig: EddsaSignature; - } - - interface Recoup { - // Hash of the public key of the denomination that is being revoked under - // emergency protocol (see /recoup). - h_denom_pub: HashCode; - - // We do not include any signature here, as the primary use-case for - // this emergency involves the exchange having lost its signing keys, - // so such a signature here would be pretty worthless. However, the - // exchange will not honor /recoup requests unless they are for - // denomination keys listed here. - } - - interface AggregateTransferFee { - // Per transfer wire transfer fee. - wire_fee: AmountString; - - // Per transfer closing fee. - closing_fee: AmountString; - - // What date (inclusive) does this fee go into effect? - // The different fees must cover the full time period in which - // any of the denomination keys are valid without overlap. - start_date: Timestamp; - - // What date (exclusive) does this fee stop going into effect? - // The different fees must cover the full time period in which - // any of the denomination keys are valid without overlap. - end_date: Timestamp; - - // Signature of TALER_MasterWireFeePS with - // purpose TALER_SIGNATURE_MASTER_WIRE_FEES. - sig: EddsaSignature; - } - - interface ExchangePartner { - // Base URL of the partner exchange. - partner_base_url: string; - - // Public master key of the partner exchange. - partner_master_pub: EddsaPublicKey; - - // Per exchange-to-exchange transfer (wad) fee. - wad_fee: AmountString; - - // Exchange-to-exchange wad (wire) transfer frequency. - wad_frequency: RelativeTime; - - // When did this partnership begin (under these conditions)? - start_date: Timestamp; - - // How long is this partnership expected to last? - end_date: Timestamp; - - // Signature using the exchange's offline key over - // TALER_WadPartnerSignaturePS - // with purpose TALER_SIGNATURE_MASTER_PARTNER_DETAILS. - master_sig: EddsaSignature; - } - - type DenomGroup = - | DenomGroupRsa - | DenomGroupCs - | DenomGroupRsaAgeRestricted - | DenomGroupCsAgeRestricted; - interface DenomGroupRsa extends DenomGroupCommon { - cipher: "RSA"; - - denoms: ({ - rsa_pub: RsaPublicKey; - } & DenomCommon)[]; - } - interface DenomGroupCs extends DenomGroupCommon { - cipher: "CS"; - - denoms: ({ - cs_pub: Cs25519Point; - } & DenomCommon)[]; - } - - // Binary representation of the age groups. - // The bits set in the mask mark the edges at the beginning of a next age - // group. F.e. for the age groups - // 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-21, 21-* - // the following bits are set: - // - // 31 24 16 8 0 - // | | | | | - // oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 - // - // A value of 0 means that the exchange does not support the extension for - // age-restriction. - type AgeMask = Integer; - - interface DenomGroupRsaAgeRestricted extends DenomGroupCommon { - cipher: "RSA+age_restricted"; - age_mask: AgeMask; - - denoms: ({ - rsa_pub: RsaPublicKey; - } & DenomCommon)[]; - } - interface DenomGroupCsAgeRestricted extends DenomGroupCommon { - cipher: "CS+age_restricted"; - age_mask: AgeMask; - - denoms: ({ - cs_pub: Cs25519Point; - } & DenomCommon)[]; - } - // Common attributes for all denomination groups - interface DenomGroupCommon { - // How much are coins of this denomination worth? - value: AmountString; - - // Fee charged by the exchange for withdrawing a coin of this denomination. - fee_withdraw: AmountString; - - // Fee charged by the exchange for depositing a coin of this denomination. - fee_deposit: AmountString; - - // Fee charged by the exchange for refreshing a coin of this denomination. - fee_refresh: AmountString; - - // Fee charged by the exchange for refunding a coin of this denomination. - fee_refund: AmountString; - } - interface DenomCommon { - // Signature of TALER_DenominationKeyValidityPS. - master_sig: EddsaSignature; - - // When does the denomination key become valid? - stamp_start: Timestamp; - - // When is it no longer possible to withdraw coins - // of this denomination? - stamp_expire_withdraw: Timestamp; - - // When is it no longer possible to deposit coins - // of this denomination? - stamp_expire_deposit: Timestamp; - - // Timestamp indicating by when legal disputes relating to these coins must - // be settled, as the exchange will afterwards destroy its evidence relating to - // transactions involving this coin. - stamp_expire_legal: Timestamp; - - // Set to 'true' if the exchange somehow "lost" - // the private key. The denomination was not - // necessarily revoked, but still cannot be used - // to withdraw coins at this time (theoretically, - // the private key could be recovered in the - // future; coins signed with the private key - // remain valid). - lost?: boolean; - } - type DenominationKey = RsaDenominationKey | CSDenominationKey; - interface RsaDenominationKey { - cipher: "RSA"; - - // 32-bit age mask. - age_mask: Integer; - - // RSA public key - rsa_public_key: RsaPublicKey; - } - interface CSDenominationKey { - cipher: "CS"; - - // 32-bit age mask. - age_mask: Integer; - - // Public key of the denomination. - cs_public_key: Cs25519Point; - } -} - -export namespace TalerMerchantApi { - export interface VersionResponse { - // libtool-style representation of the Merchant protocol version, see - // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning - // The format is "current:revision:age". - version: string; - - // Name of the protocol. - name: "taler-merchant"; - - // URN of the implementation (needed to interpret 'revision' in version). - // @since **v8**, may become mandatory in the future. - implementation?: string; - - // Default (!) currency supported by this backend. - // This is the currency that the backend should - // suggest by default to the user when entering - // amounts. See currencies for a list of - // supported currencies and how to render them. - currency: string; - - // How services should render currencies supported - // by this backend. Maps - // currency codes (e.g. "EUR" or "KUDOS") to - // the respective currency specification. - // All currencies in this map are supported by - // the backend. Note that the actual currency - // specifications are a *hint* for applications - // that would like *advice* on how to render amounts. - // Applications *may* ignore the currency specification - // if they know how to render currencies that they are - // used with. - currencies: { [currency: string]: CurrencySpecification }; - - // Array of exchanges trusted by the merchant. - // Since protocol **v6**. - exchanges: ExchangeConfigInfo[]; - } - - export interface ExchangeConfigInfo { - // Base URL of the exchange REST API. - base_url: string; - - // Currency for which the merchant is configured - // to trust the exchange. - // May not be the one the exchange actually uses, - // but is the only one we would trust this exchange for. - currency: string; - - // Offline master public key of the exchange. The - // /keys data must be signed with this public - // key for us to trust it. - master_pub: EddsaPublicKey; - } - export interface ClaimRequest { - // Nonce to identify the wallet that claimed the order. - nonce: string; - - // Token that authorizes the wallet to claim the order. - // *Optional* as the merchant may not have required it - // (create_token set to false in PostOrderRequest). - token?: ClaimToken; - } - - export interface ClaimResponse { - // Contract terms of the claimed order - contract_terms: ContractTerms; - - // Signature by the merchant over the contract terms. - sig: EddsaSignature; - } - - export interface PaymentResponse { - // Signature on TALER_PaymentResponsePS with the public - // key of the merchant instance. - sig: EddsaSignature; - - // Text to be shown to the point-of-sale staff as a proof of - // payment. - pos_confirmation?: string; - } - - export interface PaymentStatusRequestParams { - // Hash of the order’s contract terms (this is used to - // authenticate the wallet/customer in case - // $ORDER_ID is guessable). - // Required once an order was claimed. - contractTermHash?: string; - // Authorizes the request via the claim token that - // was returned in the PostOrderResponse. Used with - // unclaimed orders only. Whether token authorization is - // required is determined by the merchant when the - // frontend creates the order. - claimToken?: string; - // Session ID that the payment must be bound to. - // If not specified, the payment is not session-bound. - sessionId?: string; - // If specified, the merchant backend will wait up to - // timeout_ms milliseconds for completion of the payment - // before sending the HTTP response. A client must never - // rely on this behavior, as the merchant backend may return - // a response immediately. - timeout?: number; - // If set to “yes”, poll for the order’s pending refunds - // to be picked up. timeout_ms specifies how long we - // will wait for the refund. - awaitRefundObtained?: boolean; - // Indicates that we are polling for a refund above the - // given AMOUNT. timeout_ms will specify how long we - // will wait for the refund. - refund?: AmountString; - // Since protocol v9 refunded orders are only returned - // under “already_paid_order_id” if this flag is set - // explicitly to “YES”. - allowRefundedForRepurchase?: boolean; - } - export interface GetKycStatusRequestParams { - // If specified, the KYC check should return - // the KYC status only for this wire account. - // Otherwise, for all wire accounts. - wireHash?: string; - // If specified, the KYC check should return - // the KYC status only for the given exchange. - // Otherwise, for all exchanges we interacted with. - exchangeURL?: string; - // If specified, the merchant will wait up to - // timeout_ms milliseconds for the exchanges to - // confirm completion of the KYC process(es). - timeout?: number; - } - export interface GetOtpDeviceRequestParams { - // Timestamp in seconds to use when calculating - // the current OTP code of the device. Since protocol v10. - faketime?: number; - // Price to use when calculating the current OTP - // code of the device. Since protocol v10. - price?: AmountString; - } - export interface GetOrderRequestParams { - // Session ID that the payment must be bound to. - // If not specified, the payment is not session-bound. - sessionId?: string; - // Timeout in milliseconds to wait for a payment if - // the answer would otherwise be negative (long polling). - timeout?: number; - // Since protocol v9 refunded orders are only returned - // under “already_paid_order_id” if this flag is set - // explicitly to “YES”. - allowRefundedForRepurchase?: boolean; - } - export interface ListWireTransferRequestParams { - // Filter for transfers to the given bank account - // (subject and amount MUST NOT be given in the payto URI). - paytoURI?: string; - // Filter for transfers executed before the given timestamp. - before?: number; - // Filter for transfers executed after the given timestamp. - after?: number; - // At most return the given number of results. Negative for - // descending in execution time, positive for ascending in - // execution time. Default is -20. - limit?: number; - // Starting transfer_serial_id for an iteration. - offset?: string; - // Filter transfers by verification status. - verified?: boolean; - order?: "asc" | "dec"; - } - export interface ListOrdersRequestParams { - // If set to yes, only return paid orders, if no only - // unpaid orders. Do not give (or use “all”) to see all - // orders regardless of payment status. - paid?: boolean; - // If set to yes, only return refunded orders, if no only - // unrefunded orders. Do not give (or use “all”) to see - // all orders regardless of refund status. - refunded?: boolean; - // If set to yes, only return wired orders, if no only - // orders with missing wire transfers. Do not give (or - // use “all”) to see all orders regardless of wire transfer - // status. - wired?: boolean; - // At most return the given number of results. Negative - // for descending by row ID, positive for ascending by - // row ID. Default is 20. Since protocol v12. - limit?: number; - // Non-negative date in seconds after the UNIX Epoc, see delta - // for its interpretation. If not specified, we default to the - // oldest or most recent entry, depending on delta. - date?: AbsoluteTime; - // Starting product_serial_id for an iteration. - // Since protocol v12. - offset?: string; - // Timeout in milliseconds to wait for additional orders if the - // answer would otherwise be negative (long polling). Only useful - // if delta is positive. Note that the merchant MAY still return - // a response that contains fewer than delta orders. - timeout?: number; - // Since protocol v6. Filters by session ID. - sessionId?: string; - // Since protocol v6. Filters by fulfillment URL. - fulfillmentUrl?: string; - - order?: "asc" | "dec"; - } - - export interface PayRequest { - // The coins used to make the payment. - coins: CoinPaySig[]; - - // Custom inputs from the wallet for the contract. - wallet_data?: Object; - - // The session for which the payment is made (or replayed). - // Only set for session-based payments. - session_id?: string; - } - export interface CoinPaySig { - // Signature by the coin. - coin_sig: EddsaSignature; - - // Public key of the coin being spent. - coin_pub: EddsaPublicKey; - - // Signature made by the denomination public key. - ub_sig: RsaSignature; - - // The hash of the denomination public key associated with this coin. - h_denom: HashCode; - - // The amount that is subtracted from this coin with this payment. - contribution: AmountString; - - // URL of the exchange this coin was withdrawn from. - exchange_url: string; - } - - export interface StatusPaid { - type: "paid"; - - // Was the payment refunded (even partially, via refund or abort)? - refunded: boolean; - - // Is any amount of the refund still waiting to be picked up (even partially)? - refund_pending: boolean; - - // Amount that was refunded in total. - refund_amount: AmountString; - - // Amount that already taken by the wallet. - refund_taken: AmountString; - } - export interface StatusGotoResponse { - type: "goto"; - // The client should go to the reorder URL, there a fresh - // order might be created as this one is taken by another - // customer or wallet (or repurchase detection logic may - // apply). - public_reorder_url: string; - } - export interface StatusUnpaidResponse { - type: "unpaid"; - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; - - // Status URL, can be used as a redirect target for the browser - // to show the order QR code / trigger the wallet. - fulfillment_url?: string; - - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; - } - - export interface PaidRefundStatusResponse { - // Text to be shown to the point-of-sale staff as a proof of - // payment (present only if reusable OTP algorithm is used). - pos_confirmation?: string; - - // True if the order has been subjected to - // refunds. False if it was simply paid. - refunded: boolean; - } - export interface PaidRequest { - // Signature on TALER_PaymentResponsePS with the public - // key of the merchant instance. - sig: EddsaSignature; - - // Hash of the order's contract terms (this is used to authenticate the - // wallet/customer and to enable signature verification without - // database access). - h_contract: HashCode; - - // Hash over custom inputs from the wallet for the contract. - wallet_data_hash?: HashCode; - - // Session id for which the payment is proven. - session_id: string; - } - - export interface AbortRequest { - // Hash of the order's contract terms (this is used to authenticate the - // wallet/customer in case $ORDER_ID is guessable). - h_contract: HashCode; - - // List of coins the wallet would like to see refunds for. - // (Should be limited to the coins for which the original - // payment succeeded, as far as the wallet knows.) - coins: AbortingCoin[]; - } - interface AbortingCoin { - // Public key of a coin for which the wallet is requesting an abort-related refund. - coin_pub: EddsaPublicKey; - - // The amount to be refunded (matches the original contribution) - contribution: AmountString; - - // URL of the exchange this coin was withdrawn from. - exchange_url: string; - } - export interface AbortResponse { - // List of refund responses about the coins that the wallet - // requested an abort for. In the same order as the coins - // from the original request. - // The rtransaction_id is implied to be 0. - refunds: MerchantAbortPayRefundStatus[]; - } - export type MerchantAbortPayRefundStatus = - | MerchantAbortPayRefundSuccessStatus - | MerchantAbortPayRefundFailureStatus; - // Details about why a refund failed. - export interface MerchantAbortPayRefundFailureStatus { - // Used as tag for the sum type RefundStatus sum type. - type: "failure"; - - // HTTP status of the exchange request, must NOT be 200. - exchange_status: Integer; - - // Taler error code from the exchange reply, if available. - exchange_code?: Integer; - - // If available, HTTP reply from the exchange. - exchange_reply?: Object; - } - // Additional details needed to verify the refund confirmation signature - // (h_contract_terms and merchant_pub) are already known - // to the wallet and thus not included. - export interface MerchantAbortPayRefundSuccessStatus { - // Used as tag for the sum type MerchantCoinRefundStatus sum type. - type: "success"; - - // HTTP status of the exchange request, 200 (integer) required for refund confirmations. - exchange_status: 200; - - // The EdDSA :ref:signature (binary-only) with purpose - // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the - // exchange affirming the successful refund. - exchange_sig: EddsaSignature; - - // Public EdDSA key of the exchange that was used to generate the signature. - // Should match one of the exchange's signing keys from /keys. It is given - // explicitly as the client might otherwise be confused by clock skew as to - // which signing key was used. - exchange_pub: EddsaPublicKey; - } - - export interface WalletRefundRequest { - // Hash of the order's contract terms (this is used to authenticate the - // wallet/customer). - h_contract: HashCode; - } - export interface WalletRefundResponse { - // Amount that was refunded in total. - refund_amount: AmountString; - - // Successful refunds for this payment, empty array for none. - refunds: MerchantCoinRefundStatus[]; - - // Public key of the merchant. - merchant_pub: EddsaPublicKey; - } - export type MerchantCoinRefundStatus = - | MerchantCoinRefundSuccessStatus - | MerchantCoinRefundFailureStatus; - // Details about why a refund failed. - export interface MerchantCoinRefundFailureStatus { - // Used as tag for the sum type RefundStatus sum type. - type: "failure"; - - // HTTP status of the exchange request, must NOT be 200. - exchange_status: Integer; - - // Taler error code from the exchange reply, if available. - exchange_code?: Integer; - - // If available, HTTP reply from the exchange. - exchange_reply?: Object; - - // Refund transaction ID. - rtransaction_id: Integer; - - // Public key of a coin that was refunded. - coin_pub: EddsaPublicKey; - - // Amount that was refunded, including refund fee charged by the exchange - // to the customer. - refund_amount: AmountString; - - // Timestamp when the merchant approved the refund. - // Useful for grouping refunds. - execution_time: Timestamp; - } - // Additional details needed to verify the refund confirmation signature - // (h_contract_terms and merchant_pub) are already known - // to the wallet and thus not included. - export interface MerchantCoinRefundSuccessStatus { - // Used as tag for the sum type MerchantCoinRefundStatus sum type. - type: "success"; - - // HTTP status of the exchange request, 200 (integer) required for refund confirmations. - exchange_status: 200; - - // The EdDSA :ref:signature (binary-only) with purpose - // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the - // exchange affirming the successful refund. - exchange_sig: EddsaSignature; - - // Public EdDSA key of the exchange that was used to generate the signature. - // Should match one of the exchange's signing keys from /keys. It is given - // explicitly as the client might otherwise be confused by clock skew as to - // which signing key was used. - exchange_pub: EddsaPublicKey; - - // Refund transaction ID. - rtransaction_id: Integer; - - // Public key of a coin that was refunded. - coin_pub: EddsaPublicKey; - - // Amount that was refunded, including refund fee charged by the exchange - // to the customer. - refund_amount: AmountString; - - // Timestamp when the merchant approved the refund. - // Useful for grouping refunds. - execution_time: Timestamp; - } - - interface RewardInformation { - // Exchange from which the reward will be withdrawn. Needed by the - // wallet to determine denominations, fees, etc. - exchange_url: string; - - // URL where to go after obtaining the reward. - next_url: string; - - // (Remaining) amount of the reward (including fees). - reward_amount: AmountString; - - // Timestamp indicating when the reward is set to expire (may be in the past). - // Note that rewards that have expired MAY also result in a 404 response. - expiration: Timestamp; - } - - interface RewardPickupRequest { - // List of planchets the wallet wants to use for the reward. - planchets: PlanchetDetail[]; - } - interface PlanchetDetail { - // Hash of the denomination's public key (hashed to reduce - // bandwidth consumption). - denom_pub_hash: HashCode; - - // Coin's blinded public key. - coin_ev: CoinEnvelope; - } - interface RewardResponse { - // Blind RSA signatures over the planchets. - // The order of the signatures matches the planchets list. - blind_sigs: BlindSignature[]; - } - interface BlindSignature { - // The (blind) RSA signature. Still needs to be unblinded. - blind_sig: BlindedRsaSignature; - } - - export interface InstanceConfigurationMessage { - // Name of the merchant instance to create (will become $INSTANCE). - // Must match the regex ^[A-Za-z0-9][A-Za-z0-9_.@-]+$. - id: string; - - // Merchant name corresponding to this instance. - name: string; - - // Type of the user (business or individual). - // Defaults to 'business'. Should become mandatory field - // in the future, left as optional for API compatibility for now. - user_type?: string; - - // Merchant email for customer contact. - email?: string; - - // Merchant public website. - website?: string; - - // Merchant logo. - logo?: ImageDataUrl; - - // Authentication settings for this instance - auth: InstanceAuthConfigurationMessage; - - // The merchant's physical address (to be put into contracts). - address: Location; - - // The jurisdiction under which the merchant conducts its business - // (to be put into contracts). - jurisdiction: Location; - - // Use STEFAN curves to determine default fees? - // If false, no fees are allowed by default. - // Can always be overridden by the frontend on a per-order basis. - use_stefan: boolean; - - // If the frontend does NOT specify an execution date, how long should - // we tell the exchange to wait to aggregate transactions before - // executing the wire transfer? This delay is added to the current - // time when we generate the advisory execution time for the exchange. - default_wire_transfer_delay: RelativeTime; - - // If the frontend does NOT specify a payment deadline, how long should - // offers we make be valid by default? - default_pay_delay: RelativeTime; - } - - export interface InstanceAuthConfigurationMessage { - // Type of authentication. - // "external": The mechant backend does not do - // any authentication checks. Instead an API - // gateway must do the authentication. - // "token": The merchant checks an auth token. - // See "token" for details. - method: "external" | "token"; - - // For method "token", this field is mandatory. - // The token MUST begin with the string "secret-token:". - // After the auth token has been set (with method "token"), - // the value must be provided in a "Authorization: Bearer $token" - // header. - token?: AccessToken; - } - - export interface InstanceReconfigurationMessage { - // Merchant name corresponding to this instance. - name: string; - - // Type of the user (business or individual). - // Defaults to 'business'. Should become mandatory field - // in the future, left as optional for API compatibility for now. - user_type?: string; - - // Merchant email for customer contact. - email?: string; - - // Merchant public website. - website?: string; - - // Merchant logo. - logo?: ImageDataUrl; - - // The merchant's physical address (to be put into contracts). - address: Location; - - // The jurisdiction under which the merchant conducts its business - // (to be put into contracts). - jurisdiction: Location; - - // Use STEFAN curves to determine default fees? - // If false, no fees are allowed by default. - // Can always be overridden by the frontend on a per-order basis. - use_stefan: boolean; - - // If the frontend does NOT specify an execution date, how long should - // we tell the exchange to wait to aggregate transactions before - // executing the wire transfer? This delay is added to the current - // time when we generate the advisory execution time for the exchange. - default_wire_transfer_delay: RelativeTime; - - // If the frontend does NOT specify a payment deadline, how long should - // offers we make be valid by default? - default_pay_delay: RelativeTime; - } - - export interface InstancesResponse { - // List of instances that are present in the backend (see Instance). - instances: Instance[]; - } - - export interface Instance { - // Merchant name corresponding to this instance. - name: string; - - // Type of the user ("business" or "individual"). - user_type: string; - - // Merchant public website. - website?: string; - - // Merchant logo. - logo?: ImageDataUrl; - - // Merchant instance this response is about ($INSTANCE). - id: string; - - // Public key of the merchant/instance, in Crockford Base32 encoding. - merchant_pub: EddsaPublicKey; - - // List of the payment targets supported by this instance. Clients can - // specify the desired payment target in /order requests. Note that - // front-ends do not have to support wallets selecting payment targets. - payment_targets: string[]; - - // Has this instance been deleted (but not purged)? - deleted: boolean; - } - - export interface QueryInstancesResponse { - // Merchant name corresponding to this instance. - name: string; - - // Type of the user ("business" or "individual"). - user_type: string; - - // Merchant email for customer contact. - email?: string; - - // Merchant public website. - website?: string; - - // Merchant logo. - logo?: ImageDataUrl; - - // Public key of the merchant/instance, in Crockford Base32 encoding. - merchant_pub: EddsaPublicKey; - - // The merchant's physical address (to be put into contracts). - address: Location; - - // The jurisdiction under which the merchant conducts its business - // (to be put into contracts). - jurisdiction: Location; - - // Use STEFAN curves to determine default fees? - // If false, no fees are allowed by default. - // Can always be overridden by the frontend on a per-order basis. - use_stefan: boolean; - - // If the frontend does NOT specify an execution date, how long should - // we tell the exchange to wait to aggregate transactions before - // executing the wire transfer? This delay is added to the current - // time when we generate the advisory execution time for the exchange. - default_wire_transfer_delay: RelativeTime; - - // If the frontend does NOT specify a payment deadline, how long should - // offers we make be valid by default? - default_pay_delay: RelativeTime; - - // Authentication configuration. - // Does not contain the token when token auth is configured. - auth: { - method: "external" | "token"; - }; - } - - export interface AccountKycRedirects { - // Array of pending KYCs. - pending_kycs: MerchantAccountKycRedirect[]; - - // Array of exchanges with no reply. - timeout_kycs: ExchangeKycTimeout[]; - } - - export interface MerchantAccountKycRedirect { - // URL that the user should open in a browser to - // proceed with the KYC process (as returned - // by the exchange's /kyc-check/ endpoint). - // Optional, missing if the account is blocked - // due to AML and not due to KYC. - kyc_url?: string; - - // AML status of the account. - aml_status: Integer; - - // Base URL of the exchange this is about. - exchange_url: string; - - // Our bank wire account this is about. - payto_uri: PaytoString; - } - - export interface ExchangeKycTimeout { - // Base URL of the exchange this is about. - exchange_url: string; - - // Numeric error code indicating errors the exchange - // returned, or TALER_EC_INVALID for none. - exchange_code: number; - - // HTTP status code returned by the exchange when we asked for - // information about the KYC status. - // 0 if there was no response at all. - exchange_http_status: number; - } - - export interface AccountAddDetails { - // payto:// URI of the account. - payto_uri: PaytoString; - - // URL from where the merchant can download information - // about incoming wire transfers to this account. - credit_facade_url?: string; - - // Credentials to use when accessing the credit facade. - // Never returned on a GET (as this may be somewhat - // sensitive data). Can be set in POST - // or PATCH requests to update (or delete) credentials. - // To really delete credentials, set them to the type: "none". - credit_facade_credentials?: FacadeCredentials; - } - - export type FacadeCredentials = - | NoFacadeCredentials - | BasicAuthFacadeCredentials; - export interface NoFacadeCredentials { - type: "none"; - } - export interface BasicAuthFacadeCredentials { - type: "basic"; - - // Username to use to authenticate - username: string; - - // Password to use to authenticate - password: string; - } - export interface AccountAddResponse { - // Hash over the wire details (including over the salt). - h_wire: HashCode; - - // Salt used to compute h_wire. - salt: HashCode; - } - - export interface AccountPatchDetails { - // URL from where the merchant can download information - // about incoming wire transfers to this account. - credit_facade_url?: string; - - // Credentials to use when accessing the credit facade. - // Never returned on a GET (as this may be somewhat - // sensitive data). Can be set in POST - // or PATCH requests to update (or delete) credentials. - // To really delete credentials, set them to the type: "none". - // If the argument is omitted, the old credentials - // are simply preserved. - credit_facade_credentials?: FacadeCredentials; - } - - export interface AccountsSummaryResponse { - // List of accounts that are known for the instance. - accounts: BankAccountEntry[]; - } - - // TODO: missing in docs - export interface BankAccountEntry { - // payto:// URI of the account. - payto_uri: PaytoString; - - // Hash over the wire details (including over the salt). - h_wire: HashCode; - - // true if this account is active, - // false if it is historic. - active?: boolean; - } - export interface BankAccountDetail { - // payto:// URI of the account. - payto_uri: PaytoString; - - // Hash over the wire details (including over the salt). - h_wire: HashCode; - - // Salt used to compute h_wire. - salt: HashCode; - - // URL from where the merchant can download information - // about incoming wire transfers to this account. - credit_facade_url?: string; - - // true if this account is active, - // false if it is historic. - active?: boolean; - } - - export interface ProductAddDetail { - // Product ID to use. - product_id: string; - - // Human-readable product description. - description: string; - - // Map from IETF BCP 47 language tags to localized descriptions. - description_i18n?: { [lang_tag: string]: string }; - - // Unit in which the product is measured (liters, kilograms, packages, etc.). - unit: string; - - // The price for one unit of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: AmountString; - - // An optional base64-encoded product image. - image?: ImageDataUrl; - - // A list of taxes paid by the merchant for one unit of this product. - taxes?: Tax[]; - - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stock: Integer; - - // Identifies where the product is in stock. - address?: Location; - - // Identifies when we expect the next restocking to happen. - next_restock?: Timestamp; - - // Minimum age buyer must have (in years). Default is 0. - minimum_age?: Integer; - } - - export interface ProductPatchDetail { - // Human-readable product description. - description: string; - - // Map from IETF BCP 47 language tags to localized descriptions. - description_i18n?: { [lang_tag: string]: string }; - - // Unit in which the product is measured (liters, kilograms, packages, etc.). - unit: string; - - // The price for one unit of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: AmountString; - - // An optional base64-encoded product image. - image?: ImageDataUrl; - - // A list of taxes paid by the merchant for one unit of this product. - taxes?: Tax[]; - - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stock: Integer; - - // Number of units of the product that were lost (spoiled, stolen, etc.). - total_lost?: Integer; - - // Identifies where the product is in stock. - address?: Location; - - // Identifies when we expect the next restocking to happen. - next_restock?: Timestamp; - - // Minimum age buyer must have (in years). Default is 0. - minimum_age?: Integer; - } - - export interface InventorySummaryResponse { - // List of products that are present in the inventory. - products: InventoryEntry[]; - } - - export interface InventoryEntry { - // Product identifier, as found in the product. - product_id: string; - // product_serial_id of the product in the database. - product_serial: Integer; - } - - export interface FullInventoryDetailsResponse { - // List of products that are present in the inventory. - products: MerchantPosProductDetail[]; - - // List of categories in the inventory. - categories: MerchantCategory[]; - } - - export interface MerchantPosProductDetail { - // A unique numeric ID of the product - product_serial: number; - - // A merchant-internal unique identifier for the product - product_id?: string; - - // A list of category IDs this product belongs to. - // Typically, a product only belongs to one category, but more than one is supported. - categories: number[]; - - // Human-readable product description. - description: string; - - // Map from IETF BCP 47 language tags to localized descriptions. - description_i18n: { [lang_tag: string]: string }; - - // Unit in which the product is measured (liters, kilograms, packages, etc.). - unit: string; - - // The price for one unit of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: AmountString; - - // An optional base64-encoded product image. - image?: ImageDataUrl; - - // A list of taxes paid by the merchant for one unit of this product. - taxes?: Tax[]; - - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // Optional, if missing treat as "infinite". - total_stock?: Integer; - - // Minimum age buyer must have (in years). - minimum_age?: Integer; - } - - export interface MerchantCategory { - // A unique numeric ID of the category - id: number; - - // The name of the category. This will be shown to users and used in the order summary. - name: string; - - // Map from IETF BCP 47 language tags to localized names - name_i18n?: { [lang_tag: string]: string }; - } - - export interface ProductDetail { - // Human-readable product description. - description: string; - - // Map from IETF BCP 47 language tags to localized descriptions. - description_i18n: { [lang_tag: string]: string }; - - // Unit in which the product is measured (liters, kilograms, packages, etc.). - unit: string; - - // The price for one unit of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: AmountString; - - // An optional base64-encoded product image. - image: ImageDataUrl; - - // A list of taxes paid by the merchant for one unit of this product. - taxes?: Tax[]; - - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stock: Integer; - - // Number of units of the product that have already been sold. - total_sold: Integer; - - // Number of units of the product that were lost (spoiled, stolen, etc.). - total_lost: Integer; - - // Identifies where the product is in stock. - address?: Location; - - // Identifies when we expect the next restocking to happen. - next_restock?: Timestamp; - - // Minimum age buyer must have (in years). - minimum_age?: Integer; - } - export interface LockRequest { - // UUID that identifies the frontend performing the lock - // Must be unique for the lifetime of the lock. - lock_uuid: string; - - // How long does the frontend intend to hold the lock? - duration: RelativeTime; - - // How many units should be locked? - quantity: Integer; - } - - export interface PostOrderRequest { - // The order must at least contain the minimal - // order detail, but can override all. - order: Order; - - // If set, the backend will then set the refund deadline to the current - // time plus the specified delay. If it's not set, refunds will not be - // possible. - refund_delay?: RelativeTime; - - // Specifies the payment target preferred by the client. Can be used - // to select among the various (active) wire methods supported by the instance. - payment_target?: string; - - // Specifies that some products are to be included in the - // order from the inventory. For these inventory management - // is performed (so the products must be in stock) and - // details are completed from the product data of the backend. - inventory_products?: MinimalInventoryProduct[]; - - // Specifies a lock identifier that was used to - // lock a product in the inventory. Only useful if - // inventory_products is set. Used in case a frontend - // reserved quantities of the individual products while - // the shopping cart was being built. Multiple UUIDs can - // be used in case different UUIDs were used for different - // products (i.e. in case the user started with multiple - // shopping sessions that were combined during checkout). - lock_uuids?: string[]; - - // Should a token for claiming the order be generated? - // False can make sense if the ORDER_ID is sufficiently - // high entropy to prevent adversarial claims (like it is - // if the backend auto-generates one). Default is 'true'. - create_token?: boolean; - - // OTP device ID to associate with the order. - // This parameter is optional. - otp_id?: string; - } - - export type Order = MinimalOrderDetail & Partial<ContractTerms>; - - export interface MinimalOrderDetail { - // Amount to be paid by the customer. - amount: AmountString; - - // Short summary of the order. - summary: string; - - // See documentation of fulfillment_url in ContractTerms. - // Either fulfillment_url or fulfillment_message must be specified. - // When creating an order, the fulfillment URL can - // contain ${ORDER_ID} which will be substituted with the - // order ID of the newly created order. - fulfillment_url?: string; - - // See documentation of fulfillment_message in ContractTerms. - // Either fulfillment_url or fulfillment_message must be specified. - fulfillment_message?: string; - } - - export interface MinimalInventoryProduct { - // Which product is requested (here mandatory!). - product_id: string; - - // How many units of the product are requested. - quantity: Integer; - } - - export interface PostOrderResponse { - // Order ID of the response that was just created. - order_id: string; - - // Token that authorizes the wallet to claim the order. - // Provided only if "create_token" was set to 'true' - // in the request. - token?: ClaimToken; - } - export interface OutOfStockResponse { - // Product ID of an out-of-stock item. - product_id: string; - - // Requested quantity. - requested_quantity: Integer; - - // Available quantity (must be below requested_quantity). - available_quantity: Integer; - - // When do we expect the product to be again in stock? - // Optional, not given if unknown. - restock_expected?: Timestamp; - } - - export interface OrderHistory { - // Timestamp-sorted array of all orders matching the query. - // The order of the sorting depends on the sign of delta. - orders: OrderHistoryEntry[]; - } - export interface OrderHistoryEntry { - // Order ID of the transaction related to this entry. - order_id: string; - - // Row ID of the order in the database. - row_id: number; - - // When the order was created. - timestamp: Timestamp; - - // The amount of money the order is for. - amount: AmountString; - - // The summary of the order. - summary: string; - - // Whether some part of the order is refundable, - // that is the refund deadline has not yet expired - // and the total amount refunded so far is below - // the value of the original transaction. - refundable: boolean; - - // Whether the order has been paid or not. - paid: boolean; - } - - export type MerchantOrderStatusResponse = - | CheckPaymentPaidResponse - | CheckPaymentClaimedResponse - | CheckPaymentUnpaidResponse; - export interface CheckPaymentPaidResponse { - // The customer paid for this contract. - order_status: "paid"; - - // Was the payment refunded (even partially)? - refunded: boolean; - - // True if there are any approved refunds that the wallet has - // not yet obtained. - refund_pending: boolean; - - // Did the exchange wire us the funds? - wired: boolean; - - // Total amount the exchange deposited into our bank account - // for this contract, excluding fees. - deposit_total: AmountString; - - // Numeric error code indicating errors the exchange - // encountered tracking the wire transfer for this purchase (before - // we even got to specific coin issues). - // 0 if there were no issues. - exchange_code: number; - - // HTTP status code returned by the exchange when we asked for - // information to track the wire transfer for this purchase. - // 0 if there were no issues. - exchange_http_status: number; - - // Total amount that was refunded, 0 if refunded is false. - refund_amount: AmountString; - - // Contract terms. - contract_terms: ContractTerms; - - // The wire transfer status from the exchange for this order if - // available, otherwise empty array. - wire_details: TransactionWireTransfer[]; - - // Reports about trouble obtaining wire transfer details, - // empty array if no trouble were encountered. - wire_reports: TransactionWireReport[]; - - // The refund details for this order. One entry per - // refunded coin; empty array if there are no refunds. - refund_details: RefundDetails[]; - - // Status URL, can be used as a redirect target for the browser - // to show the order QR code / trigger the wallet. - order_status_url: string; - } - export interface CheckPaymentClaimedResponse { - // A wallet claimed the order, but did not yet pay for the contract. - order_status: "claimed"; - - // Contract terms. - contract_terms: ContractTerms; - } - export interface CheckPaymentUnpaidResponse { - // The order was neither claimed nor paid. - order_status: "unpaid"; - - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; - - // when was the order created - creation_time: Timestamp; - - // Order summary text. - summary: string; - - // Total amount of the order (to be paid by the customer). - total_amount: AmountString; - - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; - - // Fulfillment URL of an already paid order. Only given if under this - // session an already paid order with a fulfillment URL exists. - already_paid_fulfillment_url?: string; - - // Status URL, can be used as a redirect target for the browser - // to show the order QR code / trigger the wallet. - order_status_url: string; - - // We do we NOT return the contract terms here because they may not - // exist in case the wallet did not yet claim them. - } - export interface RefundDetails { - // Reason given for the refund. - reason: string; - - // Set to true if a refund is still available for the wallet for this payment. - pending: boolean; - - // When was the refund approved. - timestamp: Timestamp; - - // Total amount that was refunded (minus a refund fee). - amount: AmountString; - } - export interface TransactionWireTransfer { - // Responsible exchange. - exchange_url: string; - - // 32-byte wire transfer identifier. - wtid: Base32; - - // Execution time of the wire transfer. - execution_time: Timestamp; - - // Total amount that has been wire transferred - // to the merchant. - amount: AmountString; - - // Was this transfer confirmed by the merchant via the - // POST /transfers API, or is it merely claimed by the exchange? - confirmed: boolean; - } - export interface TransactionWireReport { - // Numerical error code. - code: number; - - // Human-readable error description. - hint: string; - - // Numerical error code from the exchange. - exchange_code: number; - - // HTTP status code received from the exchange. - exchange_http_status: number; - - // Public key of the coin for which we got the exchange error. - coin_pub: CoinPublicKey; - } - - export interface ForgetRequest { - // Array of valid JSON paths to forgettable fields in the order's - // contract terms. - fields: string[]; - } - - export interface RefundRequest { - // Amount to be refunded. - refund: AmountString; - - // Human-readable refund justification. - reason: string; - } - export interface MerchantRefundResponse { - // URL (handled by the backend) that the wallet should access to - // trigger refund processing. - // taler://refund/... - taler_refund_uri: string; - - // Contract hash that a client may need to authenticate an - // HTTP request to obtain the above URI in a wallet-friendly way. - h_contract: HashCode; - } - - export interface TransferInformation { - // How much was wired to the merchant (minus fees). - credit_amount: AmountString; - - // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value). - wtid: WireTransferIdentifierRawP; - - // Target account that received the wire transfer. - payto_uri: PaytoString; - - // Base URL of the exchange that made the wire transfer. - exchange_url: string; - } - - export interface TransferList { - // List of all the transfers that fit the filter that we know. - transfers: TransferDetails[]; - } - export interface TransferDetails { - // How much was wired to the merchant (minus fees). - credit_amount: AmountString; - - // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value). - wtid: WireTransferIdentifierRawP; - - // Target account that received the wire transfer. - payto_uri: PaytoString; - - // Base URL of the exchange that made the wire transfer. - exchange_url: string; - - // Serial number identifying the transfer in the merchant backend. - // Used for filtering via offset. - transfer_serial_id: number; - - // Time of the execution of the wire transfer by the exchange, according to the exchange - // Only provided if we did get an answer from the exchange. - execution_time?: Timestamp; - - // True if we checked the exchange's answer and are happy with it. - // False if we have an answer and are unhappy, missing if we - // do not have an answer from the exchange. - verified?: boolean; - - // True if the merchant uses the POST /transfers API to confirm - // that this wire transfer took place (and it is thus not - // something merely claimed by the exchange). - confirmed?: boolean; - } - - export interface OtpDeviceAddDetails { - // Device ID to use. - otp_device_id: string; - - // Human-readable description for the device. - otp_device_description: string; - - // A key encoded with RFC 3548 Base32. - // IMPORTANT: This is not using the typical - // Taler base32-crockford encoding. - // Instead it uses the RFC 3548 encoding to - // be compatible with the TOTP standard. - otp_key: string; - - // Algorithm for computing the POS confirmation. - // "NONE" or 0: No algorithm (no pos confirmation will be generated) - // "TOTP_WITHOUT_PRICE" or 1: Without amounts (typical OTP device) - // "TOTP_WITH_PRICE" or 2: With amounts (special-purpose OTP device) - // The "String" variants are supported @since protocol **v7**. - otp_algorithm: Integer | string; - - // Counter for counter-based OTP devices. - otp_ctr?: Integer; - } - - export interface OtpDevicePatchDetails { - // Human-readable description for the device. - otp_device_description: string; - - // A key encoded with RFC 3548 Base32. - // IMPORTANT: This is not using the typical - // Taler base32-crockford encoding. - // Instead it uses the RFC 3548 encoding to - // be compatible with the TOTP standard. - otp_key: string; - - // Algorithm for computing the POS confirmation. - otp_algorithm: Integer; - - // Counter for counter-based OTP devices. - otp_ctr?: Integer; - } - - export interface OtpDeviceSummaryResponse { - // Array of devices that are present in our backend. - otp_devices: OtpDeviceEntry[]; - } - export interface OtpDeviceEntry { - // Device identifier. - otp_device_id: string; - - // Human-readable description for the device. - device_description: string; - } - - export interface OtpDeviceDetails { - // Human-readable description for the device. - device_description: string; - - // Algorithm for computing the POS confirmation. - // - // Currently, the following numbers are defined: - // 0: None - // 1: TOTP without price - // 2: TOTP with price - otp_algorithm: Integer; - - // Counter for counter-based OTP devices. - otp_ctr?: Integer; - - // Current time for time-based OTP devices. - // Will match the faketime argument of the - // query if one was present, otherwise the current - // time at the backend. - // - // Available since protocol **v10**. - otp_timestamp: Integer; - - // Current OTP confirmation string of the device. - // Matches exactly the string that would be returned - // as part of a payment confirmation for the given - // amount and time (so may contain multiple OTP codes). - // - // If the otp_algorithm is time-based, the code is - // returned for the current time, or for the faketime - // if a TIMESTAMP query argument was provided by the client. - // - // When using OTP with counters, the counter is **NOT** - // increased merely because this endpoint created - // an OTP code (this is a GET request, after all!). - // - // If the otp_algorithm requires an amount, the - // amount argument must be specified in the - // query, otherwise the otp_code is not - // generated. - // - // This field is *optional* in the response, as it is - // only provided if we could compute it based on the - // otp_algorithm and matching client query arguments. - // - // Available since protocol **v10**. - otp_code?: string; - } - export interface TemplateAddDetails { - // Template ID to use. - template_id: string; - - // Human-readable description for the template. - template_description: string; - - // OTP device ID. - // This parameter is optional. - otp_id?: string; - - // Additional information in a separate template. - template_contract: TemplateContractDetails; - - // Key-value pairs matching a subset of the - // fields from template_contract that are - // user-editable defaults for this template. - // Since protocol **v13**. - editable_defaults?: TemplateContractDetailsDefaults; - } - export interface TemplateContractDetails { - // Human-readable summary for the template. - summary?: string; - - // Required currency for payments to the template. - // The user may specify any amount, but it must be - // in this currency. - // This parameter is optional and should not be present - // if "amount" is given. - currency?: string; - - // The price is imposed by the merchant and cannot be changed by the customer. - // This parameter is optional. - amount?: AmountString; - - // Minimum age buyer must have (in years). Default is 0. - minimum_age: Integer; - - // The time the customer need to pay before his order will be deleted. - // It is deleted if the customer did not pay and if the duration is over. - pay_duration: RelativeTime; - } - - export interface TemplateContractDetailsDefaults { - summary?: string; - - currency?: string; - - /** - * Amount *or* a plain currency string. - */ - amount?: string; - } - - export interface TemplatePatchDetails { - // Human-readable description for the template. - template_description: string; - - // OTP device ID. - // This parameter is optional. - otp_id?: string; - - // Additional information in a separate template. - template_contract: TemplateContractDetails; - - // Key-value pairs matching a subset of the - // fields from template_contract that are - // user-editable defaults for this template. - // Since protocol **v13**. - editable_defaults?: TemplateContractDetailsDefaults; - } - - export interface TemplateSummaryResponse { - // List of templates that are present in our backend. - templates: TemplateEntry[]; - } - - export interface TemplateEntry { - // Template identifier, as found in the template. - template_id: string; - - // Human-readable description for the template. - template_description: string; - } - - export interface WalletTemplateDetails { - // Hard-coded information about the contrac terms - // for this template. - template_contract: TemplateContractDetails; - - // Key-value pairs matching a subset of the - // fields from template_contract that are - // user-editable defaults for this template. - // Since protocol **v13**. - editable_defaults?: TemplateContractDetailsDefaults; - } - - export interface TemplateDetails { - // Human-readable description for the template. - template_description: string; - - // OTP device ID. - // This parameter is optional. - otp_id?: string; - - // Additional information in a separate template. - template_contract: TemplateContractDetails; - - // Key-value pairs matching a subset of the - // fields from template_contract that are - // user-editable defaults for this template. - // Since protocol **v13**. - editable_defaults?: TemplateContractDetailsDefaults; - } - export interface UsingTemplateDetails { - // Summary of the template - summary?: string; - - // The amount entered by the customer. - amount?: AmountString; - } - - export interface WebhookAddDetails { - // Webhook ID to use. - webhook_id: string; - - // The event of the webhook: why the webhook is used. - event_type: string; - - // URL of the webhook where the customer will be redirected. - url: string; - - // Method used by the webhook - http_method: string; - - // Header template of the webhook - header_template?: string; - - // Body template by the webhook - body_template?: string; - } - - export interface WebhookPatchDetails { - // The event of the webhook: why the webhook is used. - event_type: string; - - // URL of the webhook where the customer will be redirected. - url: string; - - // Method used by the webhook - http_method: string; - - // Header template of the webhook - header_template?: string; - - // Body template by the webhook - body_template?: string; - } - - export interface WebhookSummaryResponse { - // Return webhooks that are present in our backend. - webhooks: WebhookEntry[]; - } - - export interface WebhookEntry { - // Webhook identifier, as found in the webhook. - webhook_id: string; - - // The event of the webhook: why the webhook is used. - event_type: string; - } - - export interface WebhookDetails { - // The event of the webhook: why the webhook is used. - event_type: string; - - // URL of the webhook where the customer will be redirected. - url: string; - - // Method used by the webhook - http_method: string; - - // Header template of the webhook - header_template?: string; - - // Body template by the webhook - body_template?: string; - } - - export interface TokenFamilyCreateRequest { - // Identifier for the token family consisting of unreserved characters - // according to RFC 3986. - slug: string; - - // Human-readable name for the token family. - name: string; - - // Human-readable description for the token family. - description: string; - - // Optional map from IETF BCP 47 language tags to localized descriptions. - description_i18n?: { [lang_tag: string]: string }; - - // Start time of the token family's validity period. - // If not specified, merchant backend will use the current time. - valid_after?: Timestamp; - - // End time of the token family's validity period. - valid_before: Timestamp; - - // Validity duration of an issued token. - duration: RelativeTime; - - // Kind of the token family. - kind: TokenFamilyKind; - } - - export enum TokenFamilyKind { - Discount = "discount", - Subscription = "subscription", - } - - export interface TokenFamilyUpdateRequest { - // Human-readable name for the token family. - name: string; - - // Human-readable description for the token family. - description: string; - - // Optional map from IETF BCP 47 language tags to localized descriptions. - description_i18n: { [lang_tag: string]: string }; - - // Start time of the token family's validity period. - valid_after: Timestamp; - - // End time of the token family's validity period. - valid_before: Timestamp; - - // Validity duration of an issued token. - duration: RelativeTime; - } - - export interface TokenFamiliesList { - // All configured token families of this instance. - token_families: TokenFamilySummary[]; - } - - export interface TokenFamilySummary { - // Identifier for the token family consisting of unreserved characters - // according to RFC 3986. - slug: string; - - // Human-readable name for the token family. - name: string; - - // Start time of the token family's validity period. - valid_after: Timestamp; - - // End time of the token family's validity period. - valid_before: Timestamp; - - // Kind of the token family. - kind: TokenFamilyKind; - } - - export interface TokenFamilyDetails { - // Identifier for the token family consisting of unreserved characters - // according to RFC 3986. - slug: string; - - // Human-readable name for the token family. - name: string; - - // Human-readable description for the token family. - description: string; - - // Optional map from IETF BCP 47 language tags to localized descriptions. - description_i18n?: { [lang_tag: string]: string }; - - // Start time of the token family's validity period. - valid_after: Timestamp; - - // End time of the token family's validity period. - valid_before: Timestamp; - - // Validity duration of an issued token. - duration: RelativeTime; - - // Kind of the token family. - kind: TokenFamilyKind; - - // How many tokens have been issued for this family. - issued: Integer; - - // How many tokens have been redeemed for this family. - redeemed: Integer; - } - export interface ContractTerms { - // Human-readable description of the whole purchase. - summary: string; - - // Map from IETF BCP 47 language tags to localized summaries. - summary_i18n?: { [lang_tag: string]: string }; - - // Unique, free-form identifier for the proposal. - // Must be unique within a merchant instance. - // For merchants that do not store proposals in their DB - // before the customer paid for them, the order_id can be used - // by the frontend to restore a proposal from the information - // encoded in it (such as a short product identifier and timestamp). - order_id: string; - - // Total price for the transaction. - // The exchange will subtract deposit fees from that amount - // before transferring it to the merchant. - amount: AmountString; - - // URL where the same contract could be ordered again (if - // available). Returned also at the public order endpoint - // for people other than the actual buyer (hence public, - // in case order IDs are guessable). - public_reorder_url?: string; - - // URL that will show that the order was successful after - // it has been paid for. Optional. When POSTing to the - // merchant, the placeholder "${ORDER_ID}" will be - // replaced with the actual order ID (useful if the - // order ID is generated server-side and needs to be - // in the URL). - // Note that this placeholder can only be used once. - // Either fulfillment_url or fulfillment_message must be specified. - fulfillment_url?: string; - - // Message shown to the customer after paying for the order. - // Either fulfillment_url or fulfillment_message must be specified. - fulfillment_message?: string; - - // Map from IETF BCP 47 language tags to localized fulfillment - // messages. - fulfillment_message_i18n?: { [lang_tag: string]: string }; - - // Maximum total deposit fee accepted by the merchant for this contract. - // Overrides defaults of the merchant instance. - max_fee: AmountString; - - // List of products that are part of the purchase (see Product). - products: Product[]; - - // Time when this contract was generated. - timestamp: Timestamp; - - // After this deadline has passed, no refunds will be accepted. - refund_deadline: Timestamp; - - // After this deadline, the merchant won't accept payments for the contract. - pay_deadline: Timestamp; - - // Transfer deadline for the exchange. Must be in the - // deposit permissions of coins used to pay for this order. - wire_transfer_deadline: Timestamp; - - // Merchant's public key used to sign this proposal; this information - // is typically added by the backend. Note that this can be an ephemeral key. - merchant_pub: EddsaPublicKey; - - // Base URL of the (public!) merchant backend API. - // Must be an absolute URL that ends with a slash. - merchant_base_url: string; - - // More info about the merchant, see below. - merchant: Merchant; - - // The hash of the merchant instance's wire details. - h_wire: HashCode; - - // Wire transfer method identifier for the wire method associated with h_wire. - // The wallet may only select exchanges via a matching auditor if the - // exchange also supports this wire method. - // The wire transfer fees must be added based on this wire transfer method. - wire_method: string; - - // Exchanges that the merchant accepts even if it does not accept any auditors that audit them. - exchanges: Exchange[]; - - // Delivery location for (all!) products. - delivery_location?: Location; - - // Time indicating when the order should be delivered. - // May be overwritten by individual products. - delivery_date?: Timestamp; - - // Nonce generated by the wallet and echoed by the merchant - // in this field when the proposal is generated. - nonce: string; - - // Specifies for how long the wallet should try to get an - // automatic refund for the purchase. If this field is - // present, the wallet should wait for a few seconds after - // the purchase and then automatically attempt to obtain - // a refund. The wallet should probe until "delay" - // after the payment was successful (i.e. via long polling - // or via explicit requests with exponential back-off). - // - // In particular, if the wallet is offline - // at that time, it MUST repeat the request until it gets - // one response from the merchant after the delay has expired. - // If the refund is granted, the wallet MUST automatically - // recover the payment. This is used in case a merchant - // knows that it might be unable to satisfy the contract and - // desires for the wallet to attempt to get the refund without any - // customer interaction. Note that it is NOT an error if the - // merchant does not grant a refund. - auto_refund?: RelativeTime; - - // Extra data that is only interpreted by the merchant frontend. - // Useful when the merchant needs to store extra information on a - // contract without storing it separately in their database. - extra?: any; - - // Minimum age the buyer must have (in years). Default is 0. - // This value is at least as large as the maximum over all - // minimum age requirements of the products in this contract. - // It might also be set independent of any product, due to - // legal requirements. - minimum_age?: Integer; - } - - export interface Product { - // Merchant-internal identifier for the product. - product_id?: string; - - // Human-readable product description. - description: string; - - // Map from IETF BCP 47 language tags to localized descriptions. - description_i18n?: { [lang_tag: string]: string }; - - // The number of units of the product to deliver to the customer. - quantity?: Integer; - - // Unit in which the product is measured (liters, kilograms, packages, etc.). - unit?: string; - - // The price of the product; this is the total price for quantity times unit of this product. - price?: AmountString; - - // An optional base64-encoded product image. - image?: ImageDataUrl; - - // A list of taxes paid by the merchant for this product. Can be empty. - taxes?: Tax[]; - - // Time indicating when this product should be delivered. - delivery_date?: Timestamp; - } - - export interface Tax { - // The name of the tax. - name: string; - - // Amount paid in tax. - tax: AmountString; - } - export interface Merchant { - // The merchant's legal name of business. - name: string; - - // Label for a location with the business address of the merchant. - email?: string; - - // Label for a location with the business address of the merchant. - website?: string; - - // An optional base64-encoded product image. - logo?: ImageDataUrl; - - // Label for a location with the business address of the merchant. - address?: Location; - - // Label for a location that denotes the jurisdiction for disputes. - // Some of the typical fields for a location (such as a street address) may be absent. - jurisdiction?: Location; - } - // Delivery location, loosely modeled as a subset of - // ISO20022's PostalAddress25. - export interface Location { - // Nation with its own government. - country?: string; - - // Identifies a subdivision of a country such as state, region, county. - country_subdivision?: string; - - // Identifies a subdivision within a country sub-division. - district?: string; - - // Name of a built-up area, with defined boundaries, and a local government. - town?: string; - - // Specific location name within the town. - town_location?: string; - - // Identifier consisting of a group of letters and/or numbers that - // is added to a postal address to assist the sorting of mail. - post_code?: string; - - // Name of a street or thoroughfare. - street?: string; - - // Name of the building or house. - building_name?: string; - - // Number that identifies the position of a building on a street. - building_number?: string; - - // Free-form address lines, should not exceed 7 elements. - address_lines?: string[]; - } - interface Auditor { - // Official name. - name: string; - - // Auditor's public key. - auditor_pub: EddsaPublicKey; - - // Base URL of the auditor. - url: string; - } - export interface Exchange { - // The exchange's base URL. - url: string; - - // How much would the merchant like to use this exchange. - // The wallet should use a suitable exchange with high - // priority. The following priority values are used, but - // it should be noted that they are NOT in any way normative. - // - // 0: likely it will not work (recently seen with account - // restriction that would be bad for this merchant) - // 512: merchant does not know, might be down (merchant - // did not yet get /wire response). - // 1024: good choice (recently confirmed working) - priority: Integer; - - // Master public key of the exchange. - master_pub: EddsaPublicKey; - } - - export interface MerchantReserveCreateConfirmation { - // Public key identifying the reserve. - reserve_pub: EddsaPublicKey; - - // Wire accounts of the exchange where to transfer the funds. - accounts: ExchangeWireAccount[]; - } - - export interface TemplateEditableDetails { - // Human-readable summary for the template. - summary?: string; - - // Required currency for payments to the template. - // The user may specify any amount, but it must be - // in this currency. - // This parameter is optional and should not be present - // if "amount" is given. - currency?: string; - - // The price is imposed by the merchant and cannot be changed by the customer. - // This parameter is optional. - amount?: AmountString; - } - - export interface MerchantTemplateContractDetails { - // Human-readable summary for the template. - summary?: string; - - // The price is imposed by the merchant and cannot be changed by the customer. - // This parameter is optional. - amount?: string; - - // Minimum age buyer must have (in years). Default is 0. - minimum_age: number; - - // The time the customer need to pay before his order will be deleted. - // It is deleted if the customer did not pay and if the duration is over. - pay_duration: TalerProtocolDuration; - } - - export interface MerchantTemplateAddDetails { - // Template ID to use. - template_id: string; - - // Human-readable description for the template. - template_description: string; - - // A base64-encoded image selected by the merchant. - // This parameter is optional. - // We are not sure about it. - image?: string; - - editable_defaults?: TemplateEditableDetails; - - // Additional information in a separate template. - template_contract: MerchantTemplateContractDetails; - - // OTP device ID. - // This parameter is optional. - otp_id?: string; - } -} +export * as TalerMerchantApi from "../types-taler-merchant.js"; // Deprecated alias, for easier refactoring! export * as ChallengerApi from "../types-taler-challenger.js"; diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts @@ -34,7 +34,6 @@ export * from "./i18n.js"; export * from "./iban.js"; export * from "./invariants.js"; export * from "./kdf.js"; -export * from "./libeufin-api-types.js"; export * from "./libtool-version.js"; export * from "./logging.js"; export { diff --git a/packages/taler-util/src/libeufin-api-types.ts b/packages/taler-util/src/libeufin-api-types.ts @@ -1,31 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2023 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -export type FacadeCredentials = - | NoFacadeCredentials - | BasicAuthFacadeCredentials; -export interface NoFacadeCredentials { - type: "none"; -} -export interface BasicAuthFacadeCredentials { - type: "basic"; - - // Username to use to authenticate - username: string; - - // Password to use to authenticate - password: string; -} diff --git a/packages/taler-util/src/types-taler-common.ts b/packages/taler-util/src/types-taler-common.ts @@ -128,6 +128,10 @@ export type Timestamp = TalerProtocolTimestamp; export type RelativeTime = TalerProtocolDuration; +export type RsaSignature = string; + +export type BlindedRsaSignature = string; + /** * DD51 https://docs.taler.net/design-documents/051-fractional-digits.html */ @@ -198,6 +202,8 @@ export class WithdrawOperationStatusResponse { export type LitAmountString = `${string}:${number}`; +export type LibtoolVersionString = string; + export type DecimalNumber = string; declare const __amount_str: unique symbol; diff --git a/packages/taler-util/src/types-taler-exchange.ts b/packages/taler-util/src/types-taler-exchange.ts @@ -27,12 +27,14 @@ import { codecOptional, } from "./codec.js"; import { + PaytoString, buildCodecForUnion, codecForAmountString, codecForBoolean, codecForConstString, codecForCurrencySpecificiation, codecForMap, + codecForURN, strcmp, } from "./index.js"; import { Edx25519PublicKeyEnc } from "./taler-crypto.js"; @@ -43,7 +45,7 @@ import { codecForTimestamp, } from "./time.js"; import { - AgeMask, + AmlOfficerPublicKeyP, AmountString, Base32String, CoinPublicKeyString, @@ -52,8 +54,14 @@ import { EddsaPublicKeyString, EddsaSignatureString, HashCodeString, + Integer, InternationalizedString, + LibtoolVersionString, + PaytoHash, + RelativeTime, + RsaPublicKey, RsaPublicKeySring, + Timestamp, WireSalt, } from "./types-taler-common.js"; @@ -130,7 +138,7 @@ export const codecForDenominationPubKey = () => /** * Denomination as found in the /keys response from the exchange. */ -export class ExchangeDenomination { +export interface ExchangeDenomination { /** * Value of one coin of the denomination. */ @@ -193,7 +201,7 @@ export class ExchangeDenomination { /** * Signature by the auditor that a particular denomination key is audited. */ -export class AuditorDenomSig { +export interface AuditorDenomSig { /** * Denomination public key's hash. */ @@ -208,7 +216,7 @@ export class AuditorDenomSig { /** * Auditor information as given by the exchange in /keys. */ -export class ExchangeAuditor { +export interface ExchangeAuditor { /** * Auditor's public key. */ @@ -374,7 +382,7 @@ export interface CoinDepositPermission { * Element of the payback list that the * exchange gives us in /keys. */ -export class Recoup { +export interface Recoup { /** * The hash of the denomination public key for which the payback is offered. */ @@ -384,7 +392,7 @@ export class Recoup { /** * Structure that the exchange gives us in /keys. */ -export class ExchangeKeysJson { +export interface ExchangeKeysJson { /** * Canonical, public base URL of the exchange. */ @@ -623,48 +631,6 @@ export interface DenomGroupCsAgeRestricted extends DenomGroupCommon { } & DenomCommon)[]; } -export interface GlobalFees { - // What date (inclusive) does these fees go into effect? - start_date: TalerProtocolTimestamp; - - // What date (exclusive) does this fees stop going into effect? - end_date: TalerProtocolTimestamp; - - // Account history fee, charged when a user wants to - // obtain a reserve/account history. - history_fee: AmountString; - - // Annual fee charged for having an open account at the - // exchange. Charged to the account. If the account - // balance is insufficient to cover this fee, the account - // is automatically deleted/closed. (Note that the exchange - // will keep the account history around for longer for - // regulatory reasons.) - account_fee: AmountString; - - // Purse fee, charged only if a purse is abandoned - // and was not covered by the account limit. - purse_fee: AmountString; - - // How long will the exchange preserve the account history? - // After an account was deleted/closed, the exchange will - // retain the account history for legal reasons until this time. - history_expiration: TalerProtocolDuration; - - // Non-negative number of concurrent purses that any - // account holder is allowed to create without having - // to pay the purse_fee. - purse_account_limit: number; - - // How long does an exchange keep a purse around after a purse - // has expired (or been successfully merged)? A 'GET' request - // for a purse will succeed until the purse expiration time - // plus this value. - purse_timeout: TalerProtocolDuration; - - // Signature of TALER_GlobalFeesPS. - master_sig: string; -} /** * Wire fees as announced by the exchange. */ @@ -1413,3 +1379,518 @@ export interface BatchDepositRequestCoin { h_age_commitment?: string; } + +export enum AmlState { + normal = 0, + pending = 1, + frozen = 2, +} + +export interface AmlRecords { + // Array of AML records matching the query. + records: AmlRecord[]; +} +export interface AmlRecord { + // Which payto-address is this record about. + // Identifies a GNU Taler wallet or an affected bank account. + h_payto: PaytoHash; + + // What is the current AML state. + current_state: AmlState; + + // Monthly transaction threshold before a review will be triggered + threshold: AmountString; + + // RowID of the record. + rowid: Integer; +} + +export interface AmlDecisionDetails { + // Array of AML decisions made for this account. Possibly + // contains only the most recent decision if "history" was + // not set to 'true'. + aml_history: AmlDecisionDetail[]; + + // Array of KYC attributes obtained for this account. + kyc_attributes: KycDetail[]; +} +export interface AmlDecisionDetail { + // What was the justification given? + justification: string; + + // What is the new AML state. + new_state: Integer; + + // When was this decision made? + decision_time: Timestamp; + + // What is the new AML decision threshold (in monthly transaction volume)? + new_threshold: AmountString; + + // 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 + provider_section: string; + + // The collected KYC data. NULL if the attribute data could not + // be decrypted (internal error of the exchange, likely the + // attribute key was changed). + attributes?: Object; + + // Time when the KYC data was collected + collection_time: Timestamp; + + // Time when the validity of the KYC data will expire + expiration_time: Timestamp; +} + +export interface AmlDecision { + // Human-readable justification for the decision. + justification: string; + + // At what monthly transaction volume should the + // decision be automatically reviewed? + new_threshold: AmountString; + + // Which payto-address is the decision about? + // Identifies a GNU Taler wallet or an affected bank account. + h_payto: PaytoHash; + + // What is the new AML state (e.g. frozen, unfrozen, etc.) + // Numerical values are defined in AmlDecisionState. + new_state: Integer; + + // Signature by the AML officer over a + // TALER_MasterAmlOfficerStatusPS. + // Must have purpose TALER_SIGNATURE_MASTER_AML_KEY. + officer_sig: EddsaSignatureString; + + // When was the decision made? + decision_time: Timestamp; + + // Optional argument to impose new KYC requirements + // that the customer has to satisfy to unblock transactions. + kyc_requirements?: string[]; +} + +export interface ExchangeVersionResponse { + // libtool-style representation of the Exchange protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Name of the protocol. + name: "taler-exchange"; + + // URN of the implementation (needed to interpret 'revision' in version). + // @since v18, may become mandatory in the future. + implementation?: string; + + // Currency supported by this exchange, given + // as a currency code ("USD" or "EUR"). + currency: string; + + // How wallets should render this currency. + currency_specification: CurrencySpecification; + + // Names of supported KYC requirements. + supported_kyc_requirements: string[]; +} + +export interface WireAccount { + // payto:// URI identifying the account and wire method + payto_uri: PaytoString; + + // URI to convert amounts from or to the currency used by + // this wire account of the exchange. Missing if no + // conversion is applicable. + conversion_url?: string; + + // Restrictions that apply to bank accounts that would send + // funds to the exchange (crediting this exchange bank account). + // Optional, empty array for unrestricted. + credit_restrictions: AccountRestriction[]; + + // Restrictions that apply to bank accounts that would receive + // funds from the exchange (debiting this exchange bank account). + // Optional, empty array for unrestricted. + debit_restrictions: AccountRestriction[]; + + // Signature using the exchange's offline key over + // a TALER_MasterWireDetailsPS + // with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS. + master_sig: EddsaSignatureString; +} + +export interface ExchangeKeysResponse { + // libtool-style representation of the Exchange protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // The exchange's base URL. + base_url: string; + + // The exchange's currency or asset unit. + currency: string; + + /** + * FIXME: PARTIALLY IMPLEMENTED!! + */ + + // How wallets should render this currency. + // currency_specification: CurrencySpecification; + + // // Absolute cost offset for the STEFAN curve used + // // to (over) approximate fees payable by amount. + // stefan_abs: AmountString; + + // // Factor to multiply the logarithm of the amount + // // with to (over) approximate fees payable by amount. + // // Note that the total to be paid is first to be + // // divided by the smallest denomination to obtain + // // the value that the logarithm is to be taken of. + // stefan_log: AmountString; + + // // Linear cost factor for the STEFAN curve used + // // to (over) approximate fees payable by amount. + // // + // // Note that this is a scalar, as it is multiplied + // // with the actual amount. + // stefan_lin: Float; + + // // Type of the asset. "fiat", "crypto", "regional" + // // or "stock". Wallets should adjust their UI/UX + // // based on this value. + // asset_type: string; + + // // Array of wire accounts operated by the exchange for + // // incoming wire transfers. + // accounts: WireAccount[]; + + // // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") + // // to wire fees. + // wire_fees: { method: AggregateTransferFee[] }; + + // // List of exchanges that this exchange is partnering + // // with to enable wallet-to-wallet transfers. + // wads: ExchangePartner[]; + + // // Set to true if this exchange allows the use + // // of reserves for rewards. + // // @deprecated in protocol v18. + // rewards_allowed: false; + + // // EdDSA master public key of the exchange, used to sign entries + // // in denoms and signkeys. + // master_public_key: EddsaPublicKey; + + // // Relative duration until inactive reserves are closed; + // // not signed (!), can change without notice. + // 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. + // // Currency must match currency. + // wallet_balance_limit_without_kyc?: AmountString[]; + + // // Denominations offered by this exchange + // denominations: DenomGroup[]; + + // // Compact EdDSA signature (binary-only) over the + // // contatentation of all of the master_sigs (in reverse + // // chronological order by group) in the arrays under + // // "denominations". Signature of TALER_ExchangeKeySetPS + // exchange_sig: EddsaSignature; + + // // Public EdDSA key of the exchange that was used to generate the signature. + // // Should match one of the exchange's signing keys from signkeys. It is given + // // explicitly as the client might otherwise be confused by clock skew as to + // // which signing key was used for the exchange_sig. + // exchange_pub: EddsaPublicKey; + + // // Denominations for which the exchange currently offers/requests recoup. + // recoup: Recoup[]; + + // // Array of globally applicable fees by time range. + // global_fees: GlobalFees[]; + + // // The date when the denomination keys were last updated. + // list_issue_date: Timestamp; + + // // Auditors of the exchange. + // auditors: AuditorKeys[]; + + // // The exchange's signing keys. + // signkeys: SignKey[]; + + // // Optional field with a dictionary of (name, object) pairs defining the + // // supported and enabled extensions, such as age_restriction. + // extensions?: { name: ExtensionManifest }; + + // // Signature by the exchange master key of the SHA-256 hash of the + // // normalized JSON-object of field extensions, if it was set. + // // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. + // extensions_sig?: EddsaSignature; +} + +interface ExtensionManifest { + // The criticality of the extension MUST be provided. It has the same + // semantics as "critical" has for extensions in X.509: + // - if "true", the client must "understand" the extension before + // proceeding, + // - if "false", clients can safely skip extensions they do not + // understand. + // (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2) + critical: boolean; + + // The version information MUST be provided in Taler's protocol version + // ranges notation, see + // https://docs.taler.net/core/api-common.html#protocol-version-ranges + version: LibtoolVersionString; + + // Optional configuration object, defined by the feature itself + config?: object; +} + +interface SignKey { + // The actual exchange's EdDSA signing public key. + key: EddsaPublicKeyString; + + // Initial validity date for the signing key. + stamp_start: Timestamp; + + // Date when the exchange will stop using the signing key, allowed to overlap + // slightly with the next signing key's validity to allow for clock skew. + stamp_expire: Timestamp; + + // Date when all signatures made by the signing key expire and should + // henceforth no longer be considered valid in legal disputes. + stamp_end: Timestamp; + + // Signature over key and stamp_expire by the exchange master key. + // Signature of TALER_ExchangeSigningKeyValidityPS. + // Must have purpose TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY. + master_sig: EddsaSignatureString; +} + +interface AuditorKeys { + // The auditor's EdDSA signing public key. + auditor_pub: EddsaPublicKeyString; + + // The auditor's URL. + auditor_url: string; + + // The auditor's name (for humans). + auditor_name: string; + + // An array of denomination keys the auditor affirms with its signature. + // Note that the message only includes the hash of the public key, while the + // signature is actually over the expanded information including expiration + // times and fees. The exact format is described below. + denomination_keys: AuditorDenominationKey[]; +} + +interface AuditorDenominationKey { + // Hash of the public RSA key used to sign coins of the respective + // denomination. Note that the auditor's signature covers more than just + // the hash, but this other information is already provided in denoms and + // thus not repeated here. + denom_pub_h: HashCodeString; + + // Signature of TALER_ExchangeKeyValidityPS. + auditor_sig: EddsaSignatureString; +} + +export interface GlobalFees { + // What date (inclusive) does these fees go into effect? + start_date: Timestamp; + + // What date (exclusive) does this fees stop going into effect? + end_date: Timestamp; + + // Account history fee, charged when a user wants to + // obtain a reserve/account history. + history_fee: AmountString; + + // Annual fee charged for having an open account at the + // exchange. Charged to the account. If the account + // balance is insufficient to cover this fee, the account + // is automatically deleted/closed. (Note that the exchange + // will keep the account history around for longer for + // regulatory reasons.) + account_fee: AmountString; + + // Purse fee, charged only if a purse is abandoned + // and was not covered by the account limit. + purse_fee: AmountString; + + // How long will the exchange preserve the account history? + // After an account was deleted/closed, the exchange will + // retain the account history for legal reasons until this time. + history_expiration: RelativeTime; + + // Non-negative number of concurrent purses that any + // account holder is allowed to create without having + // to pay the purse_fee. + purse_account_limit: Integer; + + // How long does an exchange keep a purse around after a purse + // has expired (or been successfully merged)? A 'GET' request + // for a purse will succeed until the purse expiration time + // plus this value. + purse_timeout: RelativeTime; + + // Signature of TALER_GlobalFeesPS. + master_sig: EddsaSignatureString; +} + +export interface AggregateTransferFee { + // Per transfer wire transfer fee. + wire_fee: AmountString; + + // Per transfer closing fee. + closing_fee: AmountString; + + // What date (inclusive) does this fee go into effect? + // The different fees must cover the full time period in which + // any of the denomination keys are valid without overlap. + start_date: Timestamp; + + // What date (exclusive) does this fee stop going into effect? + // The different fees must cover the full time period in which + // any of the denomination keys are valid without overlap. + end_date: Timestamp; + + // Signature of TALER_MasterWireFeePS with + // purpose TALER_SIGNATURE_MASTER_WIRE_FEES. + sig: EddsaSignatureString; +} + +interface ExchangePartner { + // Base URL of the partner exchange. + partner_base_url: string; + + // Public master key of the partner exchange. + partner_master_pub: EddsaPublicKeyString; + + // Per exchange-to-exchange transfer (wad) fee. + wad_fee: AmountString; + + // Exchange-to-exchange wad (wire) transfer frequency. + wad_frequency: RelativeTime; + + // When did this partnership begin (under these conditions)? + start_date: Timestamp; + + // How long is this partnership expected to last? + end_date: Timestamp; + + // Signature using the exchange's offline key over + // TALER_WadPartnerSignaturePS + // with purpose TALER_SIGNATURE_MASTER_PARTNER_DETAILS. + master_sig: EddsaSignatureString; +} + +// Binary representation of the age groups. +// The bits set in the mask mark the edges at the beginning of a next age +// group. F.e. for the age groups +// 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-21, 21-* +// the following bits are set: +// +// 31 24 16 8 0 +// | | | | | +// oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 +// +// A value of 0 means that the exchange does not support the extension for +// age-restriction. +type AgeMask = Integer; + +type DenominationKey = RsaDenominationKey | CSDenominationKey; + +interface RsaDenominationKey { + cipher: "RSA"; + + // 32-bit age mask. + age_mask: Integer; + + // RSA public key + rsa_public_key: RsaPublicKey; +} + +interface CSDenominationKey { + cipher: "CS"; + + // 32-bit age mask. + age_mask: Integer; + + // Public key of the denomination. + cs_public_key: Cs25519Point; +} + +export const codecForExchangeConfig = (): Codec<ExchangeVersionResponse> => + buildCodecForObject<ExchangeVersionResponse>() + .property("version", codecForString()) + .property("name", codecForConstString("taler-exchange")) + .property("implementation", codecOptional(codecForURN())) + .property("currency", codecForString()) + .property("currency_specification", codecForCurrencySpecificiation()) + .property("supported_kyc_requirements", codecForList(codecForString())) + .build("TalerExchangeApi.ExchangeVersionResponse"); + +export const codecForExchangeKeys = (): Codec<ExchangeKeysResponse> => + buildCodecForObject<ExchangeKeysResponse>() + .property("version", codecForString()) + .property("base_url", codecForString()) + .property("currency", codecForString()) + .build("TalerExchangeApi.ExchangeKeysResponse"); +export const codecForAmlRecords = (): Codec<AmlRecords> => + buildCodecForObject<AmlRecords>() + .property("records", codecForList(codecForAmlRecord())) + .build("TalerExchangeApi.AmlRecords"); + +export const codecForAmlRecord = (): Codec<AmlRecord> => + buildCodecForObject<AmlRecord>() + .property("current_state", codecForNumber()) + .property("h_payto", codecForString()) + .property("rowid", codecForNumber()) + .property("threshold", codecForAmountString()) + .build("TalerExchangeApi.AmlRecord"); + +export const codecForAmlDecisionDetails = (): Codec<AmlDecisionDetails> => + buildCodecForObject<AmlDecisionDetails>() + .property("aml_history", codecForList(codecForAmlDecisionDetail())) + .property("kyc_attributes", codecForList(codecForKycDetail())) + .build("TalerExchangeApi.AmlDecisionDetails"); + +export const codecForAmlDecisionDetail = (): Codec<AmlDecisionDetail> => + buildCodecForObject<AmlDecisionDetail>() + .property("justification", codecForString()) + .property("new_state", codecForNumber()) + .property("decision_time", codecForTimestamp) + .property("new_threshold", codecForAmountString()) + .property("decider_pub", codecForString()) + .build("TalerExchangeApi.AmlDecisionDetail"); + +export const codecForKycDetail = (): Codec<KycDetail> => + buildCodecForObject<KycDetail>() + .property("provider_section", codecForString()) + .property("attributes", codecOptional(codecForAny())) + .property("collection_time", codecForTimestamp) + .property("expiration_time", codecForTimestamp) + .build("TalerExchangeApi.KycDetail"); + +export const codecForAmlDecision = (): Codec<AmlDecision> => + buildCodecForObject<AmlDecision>() + .property("justification", codecForString()) + .property("new_threshold", codecForAmountString()) + .property("h_payto", codecForString()) + .property("new_state", codecForNumber()) + .property("officer_sig", codecForString()) + .property("decision_time", codecForTimestamp) + .property("kyc_requirements", codecOptional(codecForList(codecForString()))) + .build("TalerExchangeApi.AmlDecision"); diff --git a/packages/taler-util/src/types-taler-merchant.ts b/packages/taler-util/src/types-taler-merchant.ts @@ -27,8 +27,22 @@ import { codecForString, codecOptional, } from "./codec.js"; -import { codecForProduct } from "./index.js"; import { + AccessToken, + CoinEnvelope, + ExchangeWireAccount, + PaytoString, + buildCodecForUnion, + codecForConstNumber, + codecForConstString, + codecForEither, + codecForExchangeWireAccount, + codecForMap, + codecForPaytoString, + codecForTalerUriString, +} from "./index.js"; +import { + AbsoluteTime, TalerProtocolDuration, TalerProtocolTimestamp, codecForDuration, @@ -36,12 +50,26 @@ import { } from "./time.js"; import { AmountString, + Base32String, + BlindedRsaSignature, + ClaimToken, + CoinPublicKey, + CurrencySpecification, + EddsaPublicKey, EddsaPublicKeyString, EddsaSignatureString, + HashCode, + HashCodeString, ImageDataUrl, Integer, InternationalizedString, + RelativeTime, + RsaSignature, + Timestamp, + WireTransferIdentifierRawP, + codecForCurrencySpecificiation, codecForInternationalizedString, + codecForURLString, } from "./types-taler-common.js"; /** @@ -702,3 +730,2626 @@ export const codecForMerchantContractTerms = (): Codec<MerchantContractTerms> => .property("extra", codecForAny()) .property("minimum_age", codecOptional(codecForNumber())) .build("MerchantContractTerms"); + +export interface VersionResponse { + // libtool-style representation of the Merchant protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Name of the protocol. + name: "taler-merchant"; + + // URN of the implementation (needed to interpret 'revision' in version). + // @since **v8**, may become mandatory in the future. + implementation?: string; + + // Default (!) currency supported by this backend. + // This is the currency that the backend should + // suggest by default to the user when entering + // amounts. See currencies for a list of + // supported currencies and how to render them. + currency: string; + + // How services should render currencies supported + // by this backend. Maps + // currency codes (e.g. "EUR" or "KUDOS") to + // the respective currency specification. + // All currencies in this map are supported by + // the backend. Note that the actual currency + // specifications are a *hint* for applications + // that would like *advice* on how to render amounts. + // Applications *may* ignore the currency specification + // if they know how to render currencies that they are + // used with. + currencies: { [currency: string]: CurrencySpecification }; + + // Array of exchanges trusted by the merchant. + // Since protocol **v6**. + exchanges: ExchangeConfigInfo[]; +} + +export interface ExchangeConfigInfo { + // Base URL of the exchange REST API. + base_url: string; + + // Currency for which the merchant is configured + // to trust the exchange. + // May not be the one the exchange actually uses, + // but is the only one we would trust this exchange for. + currency: string; + + // Offline master public key of the exchange. The + // /keys data must be signed with this public + // key for us to trust it. + master_pub: EddsaPublicKey; +} + +export interface ClaimRequest { + // Nonce to identify the wallet that claimed the order. + nonce: string; + + // Token that authorizes the wallet to claim the order. + // *Optional* as the merchant may not have required it + // (create_token set to false in PostOrderRequest). + token?: ClaimToken; +} + +export interface ClaimResponse { + // Contract terms of the claimed order + contract_terms: ContractTerms; + + // Signature by the merchant over the contract terms. + sig: EddsaSignatureString; +} + +export interface PaymentResponse { + // Signature on TALER_PaymentResponsePS with the public + // key of the merchant instance. + sig: EddsaSignatureString; + + // Text to be shown to the point-of-sale staff as a proof of + // payment. + pos_confirmation?: string; +} + +export interface PaymentStatusRequestParams { + // Hash of the order’s contract terms (this is used to + // authenticate the wallet/customer in case + // $ORDER_ID is guessable). + // Required once an order was claimed. + contractTermHash?: string; + // Authorizes the request via the claim token that + // was returned in the PostOrderResponse. Used with + // unclaimed orders only. Whether token authorization is + // required is determined by the merchant when the + // frontend creates the order. + claimToken?: string; + // Session ID that the payment must be bound to. + // If not specified, the payment is not session-bound. + sessionId?: string; + // If specified, the merchant backend will wait up to + // timeout_ms milliseconds for completion of the payment + // before sending the HTTP response. A client must never + // rely on this behavior, as the merchant backend may return + // a response immediately. + timeout?: number; + // If set to “yes”, poll for the order’s pending refunds + // to be picked up. timeout_ms specifies how long we + // will wait for the refund. + awaitRefundObtained?: boolean; + // Indicates that we are polling for a refund above the + // given AMOUNT. timeout_ms will specify how long we + // will wait for the refund. + refund?: AmountString; + // Since protocol v9 refunded orders are only returned + // under “already_paid_order_id” if this flag is set + // explicitly to “YES”. + allowRefundedForRepurchase?: boolean; +} +export interface GetKycStatusRequestParams { + // If specified, the KYC check should return + // the KYC status only for this wire account. + // Otherwise, for all wire accounts. + wireHash?: string; + // If specified, the KYC check should return + // the KYC status only for the given exchange. + // Otherwise, for all exchanges we interacted with. + exchangeURL?: string; + // If specified, the merchant will wait up to + // timeout_ms milliseconds for the exchanges to + // confirm completion of the KYC process(es). + timeout?: number; +} +export interface GetOtpDeviceRequestParams { + // Timestamp in seconds to use when calculating + // the current OTP code of the device. Since protocol v10. + faketime?: number; + // Price to use when calculating the current OTP + // code of the device. Since protocol v10. + price?: AmountString; +} +export interface GetOrderRequestParams { + // Session ID that the payment must be bound to. + // If not specified, the payment is not session-bound. + sessionId?: string; + // Timeout in milliseconds to wait for a payment if + // the answer would otherwise be negative (long polling). + timeout?: number; + // Since protocol v9 refunded orders are only returned + // under “already_paid_order_id” if this flag is set + // explicitly to “YES”. + allowRefundedForRepurchase?: boolean; +} +export interface ListWireTransferRequestParams { + // Filter for transfers to the given bank account + // (subject and amount MUST NOT be given in the payto URI). + paytoURI?: string; + // Filter for transfers executed before the given timestamp. + before?: number; + // Filter for transfers executed after the given timestamp. + after?: number; + // At most return the given number of results. Negative for + // descending in execution time, positive for ascending in + // execution time. Default is -20. + limit?: number; + // Starting transfer_serial_id for an iteration. + offset?: string; + // Filter transfers by verification status. + verified?: boolean; + order?: "asc" | "dec"; +} +export interface ListOrdersRequestParams { + // If set to yes, only return paid orders, if no only + // unpaid orders. Do not give (or use “all”) to see all + // orders regardless of payment status. + paid?: boolean; + // If set to yes, only return refunded orders, if no only + // unrefunded orders. Do not give (or use “all”) to see + // all orders regardless of refund status. + refunded?: boolean; + // If set to yes, only return wired orders, if no only + // orders with missing wire transfers. Do not give (or + // use “all”) to see all orders regardless of wire transfer + // status. + wired?: boolean; + // At most return the given number of results. Negative + // for descending by row ID, positive for ascending by + // row ID. Default is 20. Since protocol v12. + limit?: number; + // Non-negative date in seconds after the UNIX Epoc, see delta + // for its interpretation. If not specified, we default to the + // oldest or most recent entry, depending on delta. + date?: AbsoluteTime; + // Starting product_serial_id for an iteration. + // Since protocol v12. + offset?: string; + // Timeout in milliseconds to wait for additional orders if the + // answer would otherwise be negative (long polling). Only useful + // if delta is positive. Note that the merchant MAY still return + // a response that contains fewer than delta orders. + timeout?: number; + // Since protocol v6. Filters by session ID. + sessionId?: string; + // Since protocol v6. Filters by fulfillment URL. + fulfillmentUrl?: string; + + order?: "asc" | "dec"; +} + +export interface PayRequest { + // The coins used to make the payment. + coins: CoinPaySig[]; + + // Custom inputs from the wallet for the contract. + wallet_data?: Object; + + // The session for which the payment is made (or replayed). + // Only set for session-based payments. + session_id?: string; +} + +export interface CoinPaySig { + // Signature by the coin. + coin_sig: EddsaSignatureString; + + // Public key of the coin being spent. + coin_pub: EddsaPublicKey; + + // Signature made by the denomination public key. + ub_sig: RsaSignature; + + // The hash of the denomination public key associated with this coin. + h_denom: HashCodeString; + + // The amount that is subtracted from this coin with this payment. + contribution: AmountString; + + // URL of the exchange this coin was withdrawn from. + exchange_url: string; +} + +export interface StatusPaid { + type: "paid"; + + // Was the payment refunded (even partially, via refund or abort)? + refunded: boolean; + + // Is any amount of the refund still waiting to be picked up (even partially)? + refund_pending: boolean; + + // Amount that was refunded in total. + refund_amount: AmountString; + + // Amount that already taken by the wallet. + refund_taken: AmountString; +} +export interface StatusGotoResponse { + type: "goto"; + // The client should go to the reorder URL, there a fresh + // order might be created as this one is taken by another + // customer or wallet (or repurchase detection logic may + // apply). + public_reorder_url: string; +} +export interface StatusUnpaidResponse { + type: "unpaid"; + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; + + // Status URL, can be used as a redirect target for the browser + // to show the order QR code / trigger the wallet. + fulfillment_url?: string; + + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; +} + +export interface PaidRefundStatusResponse { + // Text to be shown to the point-of-sale staff as a proof of + // payment (present only if reusable OTP algorithm is used). + pos_confirmation?: string; + + // True if the order has been subjected to + // refunds. False if it was simply paid. + refunded: boolean; +} + +export interface PaidRequest { + // Signature on TALER_PaymentResponsePS with the public + // key of the merchant instance. + sig: EddsaSignatureString; + + // Hash of the order's contract terms (this is used to authenticate the + // wallet/customer and to enable signature verification without + // database access). + h_contract: HashCodeString; + + // Hash over custom inputs from the wallet for the contract. + wallet_data_hash?: HashCodeString; + + // Session id for which the payment is proven. + session_id: string; +} + +export interface AbortRequest { + // Hash of the order's contract terms (this is used to authenticate the + // wallet/customer in case $ORDER_ID is guessable). + h_contract: HashCodeString; + + // List of coins the wallet would like to see refunds for. + // (Should be limited to the coins for which the original + // payment succeeded, as far as the wallet knows.) + coins: AbortingCoin[]; +} + +export interface AbortResponse { + // List of refund responses about the coins that the wallet + // requested an abort for. In the same order as the coins + // from the original request. + // The rtransaction_id is implied to be 0. + refunds: MerchantAbortPayRefundStatus[]; +} + +export interface WalletRefundRequest { + // Hash of the order's contract terms (this is used to authenticate the + // wallet/customer). + h_contract: HashCodeString; +} + +export interface WalletRefundResponse { + // Amount that was refunded in total. + refund_amount: AmountString; + + // Successful refunds for this payment, empty array for none. + refunds: MerchantCoinRefundStatus[]; + + // Public key of the merchant. + merchant_pub: EddsaPublicKey; +} + +// Additional details needed to verify the refund confirmation signature +// (h_contract_terms and merchant_pub) are already known +// to the wallet and thus not included. +export interface MerchantCoinRefundSuccessStatus { + // Used as tag for the sum type MerchantCoinRefundStatus sum type. + type: "success"; + + // HTTP status of the exchange request, 200 (integer) required for refund confirmations. + exchange_status: 200; + + // The EdDSA :ref:signature (binary-only) with purpose + // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the + // exchange affirming the successful refund. + exchange_sig: EddsaSignatureString; + + // Public EdDSA key of the exchange that was used to generate the signature. + // Should match one of the exchange's signing keys from /keys. It is given + // explicitly as the client might otherwise be confused by clock skew as to + // which signing key was used. + exchange_pub: EddsaPublicKey; + + // Refund transaction ID. + rtransaction_id: Integer; + + // Public key of a coin that was refunded. + coin_pub: EddsaPublicKey; + + // Amount that was refunded, including refund fee charged by the exchange + // to the customer. + refund_amount: AmountString; + + // Timestamp when the merchant approved the refund. + // Useful for grouping refunds. + execution_time: Timestamp; +} + +interface RewardInformation { + // Exchange from which the reward will be withdrawn. Needed by the + // wallet to determine denominations, fees, etc. + exchange_url: string; + + // URL where to go after obtaining the reward. + next_url: string; + + // (Remaining) amount of the reward (including fees). + reward_amount: AmountString; + + // Timestamp indicating when the reward is set to expire (may be in the past). + // Note that rewards that have expired MAY also result in a 404 response. + expiration: Timestamp; +} + +interface PlanchetDetail { + // Hash of the denomination's public key (hashed to reduce + // bandwidth consumption). + denom_pub_hash: HashCodeString; + + // Coin's blinded public key. + coin_ev: CoinEnvelope; +} + +interface BlindSignature { + // The (blind) RSA signature. Still needs to be unblinded. + blind_sig: BlindedRsaSignature; +} + +export interface InstanceConfigurationMessage { + // Name of the merchant instance to create (will become $INSTANCE). + // Must match the regex ^[A-Za-z0-9][A-Za-z0-9_.@-]+$. + id: string; + + // Merchant name corresponding to this instance. + name: string; + + // Type of the user (business or individual). + // Defaults to 'business'. Should become mandatory field + // in the future, left as optional for API compatibility for now. + user_type?: string; + + // Merchant email for customer contact. + email?: string; + + // Merchant public website. + website?: string; + + // Merchant logo. + logo?: ImageDataUrl; + + // Authentication settings for this instance + auth: InstanceAuthConfigurationMessage; + + // The merchant's physical address (to be put into contracts). + address: Location; + + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; + + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_delay: RelativeTime; +} + +export interface InstanceAuthConfigurationMessage { + // Type of authentication. + // "external": The mechant backend does not do + // any authentication checks. Instead an API + // gateway must do the authentication. + // "token": The merchant checks an auth token. + // See "token" for details. + method: "external" | "token"; + + // For method "token", this field is mandatory. + // The token MUST begin with the string "secret-token:". + // After the auth token has been set (with method "token"), + // the value must be provided in a "Authorization: Bearer $token" + // header. + token?: AccessToken; +} + +export interface InstanceReconfigurationMessage { + // Merchant name corresponding to this instance. + name: string; + + // Type of the user (business or individual). + // Defaults to 'business'. Should become mandatory field + // in the future, left as optional for API compatibility for now. + user_type?: string; + + // Merchant email for customer contact. + email?: string; + + // Merchant public website. + website?: string; + + // Merchant logo. + logo?: ImageDataUrl; + + // The merchant's physical address (to be put into contracts). + address: Location; + + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; + + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_delay: RelativeTime; +} + +export interface InstancesResponse { + // List of instances that are present in the backend (see Instance). + instances: Instance[]; +} + +export interface Instance { + // Merchant name corresponding to this instance. + name: string; + + // Type of the user ("business" or "individual"). + user_type: string; + + // Merchant public website. + website?: string; + + // Merchant logo. + logo?: ImageDataUrl; + + // Merchant instance this response is about ($INSTANCE). + id: string; + + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; + + // List of the payment targets supported by this instance. Clients can + // specify the desired payment target in /order requests. Note that + // front-ends do not have to support wallets selecting payment targets. + payment_targets: string[]; + + // Has this instance been deleted (but not purged)? + deleted: boolean; +} + +export interface QueryInstancesResponse { + // Merchant name corresponding to this instance. + name: string; + + // Type of the user ("business" or "individual"). + user_type: string; + + // Merchant email for customer contact. + email?: string; + + // Merchant public website. + website?: string; + + // Merchant logo. + logo?: ImageDataUrl; + + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; + + // The merchant's physical address (to be put into contracts). + address: Location; + + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; + + // Use STEFAN curves to determine default fees? + // If false, no fees are allowed by default. + // Can always be overridden by the frontend on a per-order basis. + use_stefan: boolean; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_delay: RelativeTime; + + // Authentication configuration. + // Does not contain the token when token auth is configured. + auth: { + method: "external" | "token"; + }; +} + +export interface AccountKycRedirects { + // Array of pending KYCs. + pending_kycs: MerchantAccountKycRedirect[]; + + // Array of exchanges with no reply. + timeout_kycs: ExchangeKycTimeout[]; +} + +export interface MerchantAccountKycRedirect { + // URL that the user should open in a browser to + // proceed with the KYC process (as returned + // by the exchange's /kyc-check/ endpoint). + // Optional, missing if the account is blocked + // due to AML and not due to KYC. + kyc_url?: string; + + // AML status of the account. + aml_status: Integer; + + // Base URL of the exchange this is about. + exchange_url: string; + + // Our bank wire account this is about. + payto_uri: PaytoString; +} + +export interface ExchangeKycTimeout { + // Base URL of the exchange this is about. + exchange_url: string; + + // Numeric error code indicating errors the exchange + // returned, or TALER_EC_INVALID for none. + exchange_code: number; + + // HTTP status code returned by the exchange when we asked for + // information about the KYC status. + // 0 if there was no response at all. + exchange_http_status: number; +} + +export interface AccountAddDetails { + // payto:// URI of the account. + payto_uri: PaytoString; + + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // Credentials to use when accessing the credit facade. + // Never returned on a GET (as this may be somewhat + // sensitive data). Can be set in POST + // or PATCH requests to update (or delete) credentials. + // To really delete credentials, set them to the type: "none". + credit_facade_credentials?: FacadeCredentials; +} + +export type FacadeCredentials = + | NoFacadeCredentials + | BasicAuthFacadeCredentials; + +export interface NoFacadeCredentials { + type: "none"; +} + +export interface BasicAuthFacadeCredentials { + type: "basic"; + + // Username to use to authenticate + username: string; + + // Password to use to authenticate + password: string; +} + +export interface AccountAddResponse { + // Hash over the wire details (including over the salt). + h_wire: HashCode; + + // Salt used to compute h_wire. + salt: HashCode; +} + +export interface AccountPatchDetails { + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // Credentials to use when accessing the credit facade. + // Never returned on a GET (as this may be somewhat + // sensitive data). Can be set in POST + // or PATCH requests to update (or delete) credentials. + // To really delete credentials, set them to the type: "none". + // If the argument is omitted, the old credentials + // are simply preserved. + credit_facade_credentials?: FacadeCredentials; +} + +export interface AccountsSummaryResponse { + // List of accounts that are known for the instance. + accounts: BankAccountEntry[]; +} + +// TODO: missing in docs +export interface BankAccountEntry { + // payto:// URI of the account. + payto_uri: PaytoString; + + // Hash over the wire details (including over the salt). + h_wire: HashCode; + + // true if this account is active, + // false if it is historic. + active?: boolean; +} +export interface BankAccountDetail { + // payto:// URI of the account. + payto_uri: PaytoString; + + // Hash over the wire details (including over the salt). + h_wire: HashCode; + + // Salt used to compute h_wire. + salt: HashCode; + + // URL from where the merchant can download information + // about incoming wire transfers to this account. + credit_facade_url?: string; + + // true if this account is active, + // false if it is historic. + active?: boolean; +} + +export interface ProductAddDetail { + // Product ID to use. + product_id: string; + + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions. + description_i18n?: { [lang_tag: string]: string }; + + // Unit in which the product is measured (liters, kilograms, packages, etc.). + unit: string; + + // The price for one unit of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: AmountString; + + // An optional base64-encoded product image. + image?: ImageDataUrl; + + // A list of taxes paid by the merchant for one unit of this product. + taxes?: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stock: Integer; + + // Identifies where the product is in stock. + address?: Location; + + // Identifies when we expect the next restocking to happen. + next_restock?: Timestamp; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; +} + +export interface ProductPatchDetail { + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions. + description_i18n?: { [lang_tag: string]: string }; + + // Unit in which the product is measured (liters, kilograms, packages, etc.). + unit: string; + + // The price for one unit of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: AmountString; + + // An optional base64-encoded product image. + image?: ImageDataUrl; + + // A list of taxes paid by the merchant for one unit of this product. + taxes?: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stock: Integer; + + // Number of units of the product that were lost (spoiled, stolen, etc.). + total_lost?: Integer; + + // Identifies where the product is in stock. + address?: Location; + + // Identifies when we expect the next restocking to happen. + next_restock?: Timestamp; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; +} + +export interface InventorySummaryResponse { + // List of products that are present in the inventory. + products: InventoryEntry[]; +} + +export interface InventoryEntry { + // Product identifier, as found in the product. + product_id: string; + // product_serial_id of the product in the database. + product_serial: Integer; +} + +export interface FullInventoryDetailsResponse { + // List of products that are present in the inventory. + products: MerchantPosProductDetail[]; + + // List of categories in the inventory. + categories: MerchantCategory[]; +} + +export interface MerchantPosProductDetail { + // A unique numeric ID of the product + product_serial: number; + + // A merchant-internal unique identifier for the product + product_id?: string; + + // A list of category IDs this product belongs to. + // Typically, a product only belongs to one category, but more than one is supported. + categories: number[]; + + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions. + description_i18n: { [lang_tag: string]: string }; + + // Unit in which the product is measured (liters, kilograms, packages, etc.). + unit: string; + + // The price for one unit of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: AmountString; + + // An optional base64-encoded product image. + image?: ImageDataUrl; + + // A list of taxes paid by the merchant for one unit of this product. + taxes?: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // Optional, if missing treat as "infinite". + total_stock?: Integer; + + // Minimum age buyer must have (in years). + minimum_age?: Integer; +} + +export interface MerchantCategory { + // A unique numeric ID of the category + id: number; + + // The name of the category. This will be shown to users and used in the order summary. + name: string; + + // Map from IETF BCP 47 language tags to localized names + name_i18n?: { [lang_tag: string]: string }; +} + +export interface ProductDetail { + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions. + description_i18n: { [lang_tag: string]: string }; + + // Unit in which the product is measured (liters, kilograms, packages, etc.). + unit: string; + + // The price for one unit of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: AmountString; + + // An optional base64-encoded product image. + image: ImageDataUrl; + + // A list of taxes paid by the merchant for one unit of this product. + taxes?: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stock: Integer; + + // Number of units of the product that have already been sold. + total_sold: Integer; + + // Number of units of the product that were lost (spoiled, stolen, etc.). + total_lost: Integer; + + // Identifies where the product is in stock. + address?: Location; + + // Identifies when we expect the next restocking to happen. + next_restock?: Timestamp; + + // Minimum age buyer must have (in years). + minimum_age?: Integer; +} +export interface LockRequest { + // UUID that identifies the frontend performing the lock + // Must be unique for the lifetime of the lock. + lock_uuid: string; + + // How long does the frontend intend to hold the lock? + duration: RelativeTime; + + // How many units should be locked? + quantity: Integer; +} + +export interface PostOrderRequest { + // The order must at least contain the minimal + // order detail, but can override all. + order: Order; + + // If set, the backend will then set the refund deadline to the current + // time plus the specified delay. If it's not set, refunds will not be + // possible. + refund_delay?: RelativeTime; + + // Specifies the payment target preferred by the client. Can be used + // to select among the various (active) wire methods supported by the instance. + payment_target?: string; + + // Specifies that some products are to be included in the + // order from the inventory. For these inventory management + // is performed (so the products must be in stock) and + // details are completed from the product data of the backend. + inventory_products?: MinimalInventoryProduct[]; + + // Specifies a lock identifier that was used to + // lock a product in the inventory. Only useful if + // inventory_products is set. Used in case a frontend + // reserved quantities of the individual products while + // the shopping cart was being built. Multiple UUIDs can + // be used in case different UUIDs were used for different + // products (i.e. in case the user started with multiple + // shopping sessions that were combined during checkout). + lock_uuids?: string[]; + + // Should a token for claiming the order be generated? + // False can make sense if the ORDER_ID is sufficiently + // high entropy to prevent adversarial claims (like it is + // if the backend auto-generates one). Default is 'true'. + create_token?: boolean; + + // OTP device ID to associate with the order. + // This parameter is optional. + otp_id?: string; +} + +export type Order = MinimalOrderDetail & Partial<ContractTerms>; + +export interface MinimalOrderDetail { + // Amount to be paid by the customer. + amount: AmountString; + + // Short summary of the order. + summary: string; + + // See documentation of fulfillment_url in ContractTerms. + // Either fulfillment_url or fulfillment_message must be specified. + // When creating an order, the fulfillment URL can + // contain ${ORDER_ID} which will be substituted with the + // order ID of the newly created order. + fulfillment_url?: string; + + // See documentation of fulfillment_message in ContractTerms. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_message?: string; +} + +export interface MinimalInventoryProduct { + // Which product is requested (here mandatory!). + product_id: string; + + // How many units of the product are requested. + quantity: Integer; +} + +export interface PostOrderResponse { + // Order ID of the response that was just created. + order_id: string; + + // Token that authorizes the wallet to claim the order. + // Provided only if "create_token" was set to 'true' + // in the request. + token?: ClaimToken; +} +export interface OutOfStockResponse { + // Product ID of an out-of-stock item. + product_id: string; + + // Requested quantity. + requested_quantity: Integer; + + // Available quantity (must be below requested_quantity). + available_quantity: Integer; + + // When do we expect the product to be again in stock? + // Optional, not given if unknown. + restock_expected?: Timestamp; +} + +export interface OrderHistory { + // Timestamp-sorted array of all orders matching the query. + // The order of the sorting depends on the sign of delta. + orders: OrderHistoryEntry[]; +} + +export interface OrderHistoryEntry { + // Order ID of the transaction related to this entry. + order_id: string; + + // Row ID of the order in the database. + row_id: number; + + // When the order was created. + timestamp: Timestamp; + + // The amount of money the order is for. + amount: AmountString; + + // The summary of the order. + summary: string; + + // Whether some part of the order is refundable, + // that is the refund deadline has not yet expired + // and the total amount refunded so far is below + // the value of the original transaction. + refundable: boolean; + + // Whether the order has been paid or not. + paid: boolean; +} + +export type MerchantOrderStatusResponse = + | CheckPaymentPaidResponse + | CheckPaymentClaimedResponse + | CheckPaymentUnpaidResponse; + +export interface CheckPaymentPaidResponse { + // The customer paid for this contract. + order_status: "paid"; + + // Was the payment refunded (even partially)? + refunded: boolean; + + // True if there are any approved refunds that the wallet has + // not yet obtained. + refund_pending: boolean; + + // Did the exchange wire us the funds? + wired: boolean; + + // Total amount the exchange deposited into our bank account + // for this contract, excluding fees. + deposit_total: AmountString; + + // Numeric error code indicating errors the exchange + // encountered tracking the wire transfer for this purchase (before + // we even got to specific coin issues). + // 0 if there were no issues. + exchange_code: number; + + // HTTP status code returned by the exchange when we asked for + // information to track the wire transfer for this purchase. + // 0 if there were no issues. + exchange_http_status: number; + + // Total amount that was refunded, 0 if refunded is false. + refund_amount: AmountString; + + // Contract terms. + contract_terms: ContractTerms; + + // The wire transfer status from the exchange for this order if + // available, otherwise empty array. + wire_details: TransactionWireTransfer[]; + + // Reports about trouble obtaining wire transfer details, + // empty array if no trouble were encountered. + wire_reports: TransactionWireReport[]; + + // The refund details for this order. One entry per + // refunded coin; empty array if there are no refunds. + refund_details: RefundDetails[]; + + // Status URL, can be used as a redirect target for the browser + // to show the order QR code / trigger the wallet. + order_status_url: string; +} + +export interface CheckPaymentClaimedResponse { + // A wallet claimed the order, but did not yet pay for the contract. + order_status: "claimed"; + + // Contract terms. + contract_terms: ContractTerms; +} + +export interface CheckPaymentUnpaidResponse { + // The order was neither claimed nor paid. + order_status: "unpaid"; + + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; + + // when was the order created + creation_time: Timestamp; + + // Order summary text. + summary: string; + + // Total amount of the order (to be paid by the customer). + total_amount: AmountString; + + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; + + // Fulfillment URL of an already paid order. Only given if under this + // session an already paid order with a fulfillment URL exists. + already_paid_fulfillment_url?: string; + + // Status URL, can be used as a redirect target for the browser + // to show the order QR code / trigger the wallet. + order_status_url: string; + + // We do we NOT return the contract terms here because they may not + // exist in case the wallet did not yet claim them. +} +export interface RefundDetails { + // Reason given for the refund. + reason: string; + + // Set to true if a refund is still available for the wallet for this payment. + pending: boolean; + + // When was the refund approved. + timestamp: Timestamp; + + // Total amount that was refunded (minus a refund fee). + amount: AmountString; +} + +export interface TransactionWireTransfer { + // Responsible exchange. + exchange_url: string; + + // 32-byte wire transfer identifier. + wtid: Base32String; + + // Execution time of the wire transfer. + execution_time: Timestamp; + + // Total amount that has been wire transferred + // to the merchant. + amount: AmountString; + + // Was this transfer confirmed by the merchant via the + // POST /transfers API, or is it merely claimed by the exchange? + confirmed: boolean; +} + +export interface TransactionWireReport { + // Numerical error code. + code: number; + + // Human-readable error description. + hint: string; + + // Numerical error code from the exchange. + exchange_code: number; + + // HTTP status code received from the exchange. + exchange_http_status: number; + + // Public key of the coin for which we got the exchange error. + coin_pub: CoinPublicKey; +} + +export interface ForgetRequest { + // Array of valid JSON paths to forgettable fields in the order's + // contract terms. + fields: string[]; +} + +export interface RefundRequest { + // Amount to be refunded. + refund: AmountString; + + // Human-readable refund justification. + reason: string; +} +export interface MerchantRefundResponse { + // URL (handled by the backend) that the wallet should access to + // trigger refund processing. + // taler://refund/... + taler_refund_uri: string; + + // Contract hash that a client may need to authenticate an + // HTTP request to obtain the above URI in a wallet-friendly way. + h_contract: HashCode; +} + +export interface TransferInformation { + // How much was wired to the merchant (minus fees). + credit_amount: AmountString; + + // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value). + wtid: WireTransferIdentifierRawP; + + // Target account that received the wire transfer. + payto_uri: PaytoString; + + // Base URL of the exchange that made the wire transfer. + exchange_url: string; +} + +export interface TransferList { + // List of all the transfers that fit the filter that we know. + transfers: TransferDetails[]; +} +export interface TransferDetails { + // How much was wired to the merchant (minus fees). + credit_amount: AmountString; + + // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value). + wtid: WireTransferIdentifierRawP; + + // Target account that received the wire transfer. + payto_uri: PaytoString; + + // Base URL of the exchange that made the wire transfer. + exchange_url: string; + + // Serial number identifying the transfer in the merchant backend. + // Used for filtering via offset. + transfer_serial_id: number; + + // Time of the execution of the wire transfer by the exchange, according to the exchange + // Only provided if we did get an answer from the exchange. + execution_time?: Timestamp; + + // True if we checked the exchange's answer and are happy with it. + // False if we have an answer and are unhappy, missing if we + // do not have an answer from the exchange. + verified?: boolean; + + // True if the merchant uses the POST /transfers API to confirm + // that this wire transfer took place (and it is thus not + // something merely claimed by the exchange). + confirmed?: boolean; +} + +export interface OtpDeviceAddDetails { + // Device ID to use. + otp_device_id: string; + + // Human-readable description for the device. + otp_device_description: string; + + // A key encoded with RFC 3548 Base32. + // IMPORTANT: This is not using the typical + // Taler base32-crockford encoding. + // Instead it uses the RFC 3548 encoding to + // be compatible with the TOTP standard. + otp_key: string; + + // Algorithm for computing the POS confirmation. + // "NONE" or 0: No algorithm (no pos confirmation will be generated) + // "TOTP_WITHOUT_PRICE" or 1: Without amounts (typical OTP device) + // "TOTP_WITH_PRICE" or 2: With amounts (special-purpose OTP device) + // The "String" variants are supported @since protocol **v7**. + otp_algorithm: Integer | string; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; +} + +export interface OtpDevicePatchDetails { + // Human-readable description for the device. + otp_device_description: string; + + // A key encoded with RFC 3548 Base32. + // IMPORTANT: This is not using the typical + // Taler base32-crockford encoding. + // Instead it uses the RFC 3548 encoding to + // be compatible with the TOTP standard. + otp_key: string; + + // Algorithm for computing the POS confirmation. + otp_algorithm: Integer; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; +} + +export interface OtpDeviceSummaryResponse { + // Array of devices that are present in our backend. + otp_devices: OtpDeviceEntry[]; +} +export interface OtpDeviceEntry { + // Device identifier. + otp_device_id: string; + + // Human-readable description for the device. + device_description: string; +} + +export interface OtpDeviceDetails { + // Human-readable description for the device. + device_description: string; + + // Algorithm for computing the POS confirmation. + // + // Currently, the following numbers are defined: + // 0: None + // 1: TOTP without price + // 2: TOTP with price + otp_algorithm: Integer; + + // Counter for counter-based OTP devices. + otp_ctr?: Integer; + + // Current time for time-based OTP devices. + // Will match the faketime argument of the + // query if one was present, otherwise the current + // time at the backend. + // + // Available since protocol **v10**. + otp_timestamp: Integer; + + // Current OTP confirmation string of the device. + // Matches exactly the string that would be returned + // as part of a payment confirmation for the given + // amount and time (so may contain multiple OTP codes). + // + // If the otp_algorithm is time-based, the code is + // returned for the current time, or for the faketime + // if a TIMESTAMP query argument was provided by the client. + // + // When using OTP with counters, the counter is **NOT** + // increased merely because this endpoint created + // an OTP code (this is a GET request, after all!). + // + // If the otp_algorithm requires an amount, the + // amount argument must be specified in the + // query, otherwise the otp_code is not + // generated. + // + // This field is *optional* in the response, as it is + // only provided if we could compute it based on the + // otp_algorithm and matching client query arguments. + // + // Available since protocol **v10**. + otp_code?: string; +} +export interface TemplateAddDetails { + // Template ID to use. + template_id: string; + + // Human-readable description for the template. + template_description: string; + + // OTP device ID. + // This parameter is optional. + otp_id?: string; + + // Additional information in a separate template. + template_contract: TemplateContractDetails; + + // Key-value pairs matching a subset of the + // fields from template_contract that are + // user-editable defaults for this template. + // Since protocol **v13**. + editable_defaults?: TemplateContractDetailsDefaults; +} +export interface TemplateContractDetails { + // Human-readable summary for the template. + summary?: string; + + // Required currency for payments to the template. + // The user may specify any amount, but it must be + // in this currency. + // This parameter is optional and should not be present + // if "amount" is given. + currency?: string; + + // The price is imposed by the merchant and cannot be changed by the customer. + // This parameter is optional. + amount?: AmountString; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age: Integer; + + // The time the customer need to pay before his order will be deleted. + // It is deleted if the customer did not pay and if the duration is over. + pay_duration: RelativeTime; +} + +export interface TemplateContractDetailsDefaults { + summary?: string; + + currency?: string; + + /** + * Amount *or* a plain currency string. + */ + amount?: string; +} + +export interface TemplatePatchDetails { + // Human-readable description for the template. + template_description: string; + + // OTP device ID. + // This parameter is optional. + otp_id?: string; + + // Additional information in a separate template. + template_contract: TemplateContractDetails; + + // Key-value pairs matching a subset of the + // fields from template_contract that are + // user-editable defaults for this template. + // Since protocol **v13**. + editable_defaults?: TemplateContractDetailsDefaults; +} + +export interface TemplateSummaryResponse { + // List of templates that are present in our backend. + templates: TemplateEntry[]; +} + +export interface TemplateEntry { + // Template identifier, as found in the template. + template_id: string; + + // Human-readable description for the template. + template_description: string; +} + +export interface WalletTemplateDetails { + // Hard-coded information about the contrac terms + // for this template. + template_contract: TemplateContractDetails; + + // Key-value pairs matching a subset of the + // fields from template_contract that are + // user-editable defaults for this template. + // Since protocol **v13**. + editable_defaults?: TemplateContractDetailsDefaults; +} + +export interface TemplateDetails { + // Human-readable description for the template. + template_description: string; + + // OTP device ID. + // This parameter is optional. + otp_id?: string; + + // Additional information in a separate template. + template_contract: TemplateContractDetails; + + // Key-value pairs matching a subset of the + // fields from template_contract that are + // user-editable defaults for this template. + // Since protocol **v13**. + editable_defaults?: TemplateContractDetailsDefaults; +} +export interface UsingTemplateDetails { + // Summary of the template + summary?: string; + + // The amount entered by the customer. + amount?: AmountString; +} + +export interface WebhookAddDetails { + // Webhook ID to use. + webhook_id: string; + + // The event of the webhook: why the webhook is used. + event_type: string; + + // URL of the webhook where the customer will be redirected. + url: string; + + // Method used by the webhook + http_method: string; + + // Header template of the webhook + header_template?: string; + + // Body template by the webhook + body_template?: string; +} + +export interface WebhookPatchDetails { + // The event of the webhook: why the webhook is used. + event_type: string; + + // URL of the webhook where the customer will be redirected. + url: string; + + // Method used by the webhook + http_method: string; + + // Header template of the webhook + header_template?: string; + + // Body template by the webhook + body_template?: string; +} + +export interface WebhookSummaryResponse { + // Return webhooks that are present in our backend. + webhooks: WebhookEntry[]; +} + +export interface WebhookEntry { + // Webhook identifier, as found in the webhook. + webhook_id: string; + + // The event of the webhook: why the webhook is used. + event_type: string; +} + +export interface WebhookDetails { + // The event of the webhook: why the webhook is used. + event_type: string; + + // URL of the webhook where the customer will be redirected. + url: string; + + // Method used by the webhook + http_method: string; + + // Header template of the webhook + header_template?: string; + + // Body template by the webhook + body_template?: string; +} + +export interface TokenFamilyCreateRequest { + // Identifier for the token family consisting of unreserved characters + // according to RFC 3986. + slug: string; + + // Human-readable name for the token family. + name: string; + + // Human-readable description for the token family. + description: string; + + // Optional map from IETF BCP 47 language tags to localized descriptions. + description_i18n?: { [lang_tag: string]: string }; + + // Start time of the token family's validity period. + // If not specified, merchant backend will use the current time. + valid_after?: Timestamp; + + // End time of the token family's validity period. + valid_before: Timestamp; + + // Validity duration of an issued token. + duration: RelativeTime; + + // Kind of the token family. + kind: TokenFamilyKind; +} + +export enum TokenFamilyKind { + Discount = "discount", + Subscription = "subscription", +} + +export interface TokenFamilyUpdateRequest { + // Human-readable name for the token family. + name: string; + + // Human-readable description for the token family. + description: string; + + // Optional map from IETF BCP 47 language tags to localized descriptions. + description_i18n: { [lang_tag: string]: string }; + + // Start time of the token family's validity period. + valid_after: Timestamp; + + // End time of the token family's validity period. + valid_before: Timestamp; + + // Validity duration of an issued token. + duration: RelativeTime; +} + +export interface TokenFamiliesList { + // All configured token families of this instance. + token_families: TokenFamilySummary[]; +} + +export interface TokenFamilySummary { + // Identifier for the token family consisting of unreserved characters + // according to RFC 3986. + slug: string; + + // Human-readable name for the token family. + name: string; + + // Start time of the token family's validity period. + valid_after: Timestamp; + + // End time of the token family's validity period. + valid_before: Timestamp; + + // Kind of the token family. + kind: TokenFamilyKind; +} + +export interface TokenFamilyDetails { + // Identifier for the token family consisting of unreserved characters + // according to RFC 3986. + slug: string; + + // Human-readable name for the token family. + name: string; + + // Human-readable description for the token family. + description: string; + + // Optional map from IETF BCP 47 language tags to localized descriptions. + description_i18n?: { [lang_tag: string]: string }; + + // Start time of the token family's validity period. + valid_after: Timestamp; + + // End time of the token family's validity period. + valid_before: Timestamp; + + // Validity duration of an issued token. + duration: RelativeTime; + + // Kind of the token family. + kind: TokenFamilyKind; + + // How many tokens have been issued for this family. + issued: Integer; + + // How many tokens have been redeemed for this family. + redeemed: Integer; +} +export interface ContractTerms { + // Human-readable description of the whole purchase. + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries. + summary_i18n?: { [lang_tag: string]: string }; + + // Unique, free-form identifier for the proposal. + // Must be unique within a merchant instance. + // For merchants that do not store proposals in their DB + // before the customer paid for them, the order_id can be used + // by the frontend to restore a proposal from the information + // encoded in it (such as a short product identifier and timestamp). + order_id: string; + + // Total price for the transaction. + // The exchange will subtract deposit fees from that amount + // before transferring it to the merchant. + amount: AmountString; + + // URL where the same contract could be ordered again (if + // available). Returned also at the public order endpoint + // for people other than the actual buyer (hence public, + // in case order IDs are guessable). + public_reorder_url?: string; + + // URL that will show that the order was successful after + // it has been paid for. Optional. When POSTing to the + // merchant, the placeholder "${ORDER_ID}" will be + // replaced with the actual order ID (useful if the + // order ID is generated server-side and needs to be + // in the URL). + // Note that this placeholder can only be used once. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_url?: string; + + // Message shown to the customer after paying for the order. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_message?: string; + + // Map from IETF BCP 47 language tags to localized fulfillment + // messages. + fulfillment_message_i18n?: { [lang_tag: string]: string }; + + // Maximum total deposit fee accepted by the merchant for this contract. + // Overrides defaults of the merchant instance. + max_fee: AmountString; + + // List of products that are part of the purchase (see Product). + products: Product[]; + + // Time when this contract was generated. + timestamp: Timestamp; + + // After this deadline has passed, no refunds will be accepted. + refund_deadline: Timestamp; + + // After this deadline, the merchant won't accept payments for the contract. + pay_deadline: Timestamp; + + // Transfer deadline for the exchange. Must be in the + // deposit permissions of coins used to pay for this order. + wire_transfer_deadline: Timestamp; + + // Merchant's public key used to sign this proposal; this information + // is typically added by the backend. Note that this can be an ephemeral key. + merchant_pub: EddsaPublicKey; + + // Base URL of the (public!) merchant backend API. + // Must be an absolute URL that ends with a slash. + merchant_base_url: string; + + // More info about the merchant, see below. + merchant: Merchant; + + // The hash of the merchant instance's wire details. + h_wire: HashCode; + + // Wire transfer method identifier for the wire method associated with h_wire. + // The wallet may only select exchanges via a matching auditor if the + // exchange also supports this wire method. + // The wire transfer fees must be added based on this wire transfer method. + wire_method: string; + + // Exchanges that the merchant accepts even if it does not accept any auditors that audit them. + exchanges: Exchange[]; + + // Delivery location for (all!) products. + delivery_location?: Location; + + // Time indicating when the order should be delivered. + // May be overwritten by individual products. + delivery_date?: Timestamp; + + // Nonce generated by the wallet and echoed by the merchant + // in this field when the proposal is generated. + nonce: string; + + // Specifies for how long the wallet should try to get an + // automatic refund for the purchase. If this field is + // present, the wallet should wait for a few seconds after + // the purchase and then automatically attempt to obtain + // a refund. The wallet should probe until "delay" + // after the payment was successful (i.e. via long polling + // or via explicit requests with exponential back-off). + // + // In particular, if the wallet is offline + // at that time, it MUST repeat the request until it gets + // one response from the merchant after the delay has expired. + // If the refund is granted, the wallet MUST automatically + // recover the payment. This is used in case a merchant + // knows that it might be unable to satisfy the contract and + // desires for the wallet to attempt to get the refund without any + // customer interaction. Note that it is NOT an error if the + // merchant does not grant a refund. + auto_refund?: RelativeTime; + + // Extra data that is only interpreted by the merchant frontend. + // Useful when the merchant needs to store extra information on a + // contract without storing it separately in their database. + extra?: any; + + // Minimum age the buyer must have (in years). Default is 0. + // This value is at least as large as the maximum over all + // minimum age requirements of the products in this contract. + // It might also be set independent of any product, due to + // legal requirements. + minimum_age?: Integer; +} + +export interface Product { + // Merchant-internal identifier for the product. + product_id?: string; + + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions. + description_i18n?: { [lang_tag: string]: string }; + + // The number of units of the product to deliver to the customer. + quantity?: Integer; + + // Unit in which the product is measured (liters, kilograms, packages, etc.). + unit?: string; + + // The price of the product; this is the total price for quantity times unit of this product. + price?: AmountString; + + // An optional base64-encoded product image. + image?: ImageDataUrl; + + // A list of taxes paid by the merchant for this product. Can be empty. + taxes?: Tax[]; + + // Time indicating when this product should be delivered. + delivery_date?: Timestamp; +} + +export interface Tax { + // The name of the tax. + name: string; + + // Amount paid in tax. + tax: AmountString; +} +export interface Merchant { + // The merchant's legal name of business. + name: string; + + // Label for a location with the business address of the merchant. + email?: string; + + // Label for a location with the business address of the merchant. + website?: string; + + // An optional base64-encoded product image. + logo?: ImageDataUrl; + + // Label for a location with the business address of the merchant. + address?: Location; + + // Label for a location that denotes the jurisdiction for disputes. + // Some of the typical fields for a location (such as a street address) may be absent. + jurisdiction?: Location; +} +// Delivery location, loosely modeled as a subset of +// ISO20022's PostalAddress25. +export interface Location { + // Nation with its own government. + country?: string; + + // Identifies a subdivision of a country such as state, region, county. + country_subdivision?: string; + + // Identifies a subdivision within a country sub-division. + district?: string; + + // Name of a built-up area, with defined boundaries, and a local government. + town?: string; + + // Specific location name within the town. + town_location?: string; + + // Identifier consisting of a group of letters and/or numbers that + // is added to a postal address to assist the sorting of mail. + post_code?: string; + + // Name of a street or thoroughfare. + street?: string; + + // Name of the building or house. + building_name?: string; + + // Number that identifies the position of a building on a street. + building_number?: string; + + // Free-form address lines, should not exceed 7 elements. + address_lines?: string[]; +} +interface Auditor { + // Official name. + name: string; + + // Auditor's public key. + auditor_pub: EddsaPublicKey; + + // Base URL of the auditor. + url: string; +} +export interface Exchange { + // The exchange's base URL. + url: string; + + // How much would the merchant like to use this exchange. + // The wallet should use a suitable exchange with high + // priority. The following priority values are used, but + // it should be noted that they are NOT in any way normative. + // + // 0: likely it will not work (recently seen with account + // restriction that would be bad for this merchant) + // 512: merchant does not know, might be down (merchant + // did not yet get /wire response). + // 1024: good choice (recently confirmed working) + priority: Integer; + + // Master public key of the exchange. + master_pub: EddsaPublicKey; +} + +export interface MerchantReserveCreateConfirmation { + // Public key identifying the reserve. + reserve_pub: EddsaPublicKey; + + // Wire accounts of the exchange where to transfer the funds. + accounts: ExchangeWireAccount[]; +} + +export interface TemplateEditableDetails { + // Human-readable summary for the template. + summary?: string; + + // Required currency for payments to the template. + // The user may specify any amount, but it must be + // in this currency. + // This parameter is optional and should not be present + // if "amount" is given. + currency?: string; + + // The price is imposed by the merchant and cannot be changed by the customer. + // This parameter is optional. + amount?: AmountString; +} + +export interface MerchantTemplateContractDetails { + // Human-readable summary for the template. + summary?: string; + + // The price is imposed by the merchant and cannot be changed by the customer. + // This parameter is optional. + amount?: string; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age: number; + + // The time the customer need to pay before his order will be deleted. + // It is deleted if the customer did not pay and if the duration is over. + pay_duration: TalerProtocolDuration; +} + +export interface MerchantTemplateAddDetails { + // Template ID to use. + template_id: string; + + // Human-readable description for the template. + template_description: string; + + // A base64-encoded image selected by the merchant. + // This parameter is optional. + // We are not sure about it. + image?: string; + + editable_defaults?: TemplateEditableDetails; + + // Additional information in a separate template. + template_contract: MerchantTemplateContractDetails; + + // OTP device ID. + // This parameter is optional. + otp_id?: string; +} + +const codecForExchangeConfigInfo = (): Codec<ExchangeConfigInfo> => + buildCodecForObject<ExchangeConfigInfo>() + .property("base_url", codecForString()) + .property("currency", codecForString()) + .property("master_pub", codecForString()) + .build("TalerMerchantApi.ExchangeConfigInfo"); + +export const codecForMerchantConfig = (): Codec<VersionResponse> => + buildCodecForObject<VersionResponse>() + .property("name", codecForConstString("taler-merchant")) + .property("currency", codecForString()) + .property("version", codecForString()) + .property("currencies", codecForMap(codecForCurrencySpecificiation())) + .property("exchanges", codecForList(codecForExchangeConfigInfo())) + .build("TalerMerchantApi.VersionResponse"); + +export const codecForClaimResponse = (): Codec<ClaimResponse> => + buildCodecForObject<ClaimResponse>() + .property("contract_terms", codecForContractTerms()) + .property("sig", codecForString()) + .build("TalerMerchantApi.ClaimResponse"); + +export const codecForPaymentResponse = (): Codec<PaymentResponse> => + buildCodecForObject<PaymentResponse>() + .property("pos_confirmation", codecOptional(codecForString())) + .property("sig", codecForString()) + .build("TalerMerchantApi.PaymentResponse"); + +export const codecForStatusPaid = (): Codec<StatusPaid> => + buildCodecForObject<StatusPaid>() + .property("refund_amount", codecForAmountString()) + .property("refund_pending", codecForBoolean()) + .property("refund_taken", codecForAmountString()) + .property("refunded", codecForBoolean()) + .property("type", codecForConstString("paid")) + .build("TalerMerchantApi.StatusPaid"); + +export const codecForStatusGoto = (): Codec<StatusGotoResponse> => + buildCodecForObject<StatusGotoResponse>() + .property("public_reorder_url", codecForURLString()) + .property("type", codecForConstString("goto")) + .build("TalerMerchantApi.StatusGotoResponse"); + +export const codecForStatusStatusUnpaid = (): Codec<StatusUnpaidResponse> => + buildCodecForObject<StatusUnpaidResponse>() + .property("type", codecForConstString("unpaid")) + .property("already_paid_order_id", codecOptional(codecForString())) + .property("fulfillment_url", codecOptional(codecForString())) + .property("taler_pay_uri", codecForTalerUriString()) + .build("TalerMerchantApi.PaymentResponse"); + +export const codecForPaidRefundStatusResponse = + (): Codec<PaidRefundStatusResponse> => + buildCodecForObject<PaidRefundStatusResponse>() + .property("pos_confirmation", codecOptional(codecForString())) + .property("refunded", codecForBoolean()) + .build("TalerMerchantApi.PaidRefundStatusResponse"); + +export const codecForMerchantAbortPayRefundSuccessStatus = + (): Codec<MerchantAbortPayRefundSuccessStatus> => + buildCodecForObject<MerchantAbortPayRefundSuccessStatus>() + .property("exchange_pub", codecForString()) + .property("exchange_sig", codecForString()) + .property("exchange_status", codecForConstNumber(200)) + .property("type", codecForConstString("success")) + .build("TalerMerchantApi.MerchantAbortPayRefundSuccessStatus"); + +export const codecForMerchantAbortPayRefundFailureStatus = + (): Codec<MerchantAbortPayRefundFailureStatus> => + buildCodecForObject<MerchantAbortPayRefundFailureStatus>() + .property("exchange_code", codecForNumber()) + .property("exchange_reply", codecForAny()) + .property("exchange_status", codecForNumber()) + .property("type", codecForConstString("failure")) + .build("TalerMerchantApi.MerchantAbortPayRefundFailureStatus"); + +export const codecForMerchantAbortPayRefundStatus = + (): Codec<MerchantAbortPayRefundStatus> => + buildCodecForUnion<MerchantAbortPayRefundStatus>() + .discriminateOn("type") + .alternative("success", codecForMerchantAbortPayRefundSuccessStatus()) + .alternative("failure", codecForMerchantAbortPayRefundFailureStatus()) + .build("TalerMerchantApi.MerchantAbortPayRefundStatus"); + +export const codecForAbortResponse = (): Codec<AbortResponse> => + buildCodecForObject<AbortResponse>() + .property("refunds", codecForList(codecForMerchantAbortPayRefundStatus())) + .build("TalerMerchantApi.AbortResponse"); + +export const codecForWalletRefundResponse = (): Codec<WalletRefundResponse> => + buildCodecForObject<WalletRefundResponse>() + .property("merchant_pub", codecForString()) + .property("refund_amount", codecForAmountString()) + .property("refunds", codecForList(codecForMerchantCoinRefundStatus())) + .build("TalerMerchantApi.AbortResponse"); + +export const codecForMerchantCoinRefundSuccessStatus = + (): Codec<MerchantCoinRefundSuccessStatus> => + buildCodecForObject<MerchantCoinRefundSuccessStatus>() + .property("type", codecForConstString("success")) + .property("coin_pub", codecForString()) + .property("exchange_status", codecForConstNumber(200)) + .property("exchange_sig", codecForString()) + .property("rtransaction_id", codecForNumber()) + .property("refund_amount", codecForAmountString()) + .property("exchange_pub", codecForString()) + .property("execution_time", codecForTimestamp) + .build("TalerMerchantApi.MerchantCoinRefundSuccessStatus"); + +export const codecForMerchantCoinRefundFailureStatus = + (): Codec<MerchantCoinRefundFailureStatus> => + buildCodecForObject<MerchantCoinRefundFailureStatus>() + .property("type", codecForConstString("failure")) + .property("coin_pub", codecForString()) + .property("exchange_status", codecForNumber()) + .property("rtransaction_id", codecForNumber()) + .property("refund_amount", codecForAmountString()) + .property("exchange_code", codecOptional(codecForNumber())) + .property("exchange_reply", codecOptional(codecForAny())) + .property("execution_time", codecForTimestamp) + .build("TalerMerchantApi.MerchantCoinRefundFailureStatus"); + +export const codecForMerchantCoinRefundStatus = + (): Codec<MerchantCoinRefundStatus> => + buildCodecForUnion<MerchantCoinRefundStatus>() + .discriminateOn("type") + .alternative("success", codecForMerchantCoinRefundSuccessStatus()) + .alternative("failure", codecForMerchantCoinRefundFailureStatus()) + .build("TalerMerchantApi.MerchantCoinRefundStatus"); + +export const codecForQueryInstancesResponse = + (): Codec<QueryInstancesResponse> => + buildCodecForObject<QueryInstancesResponse>() + .property("name", codecForString()) + .property("user_type", codecForString()) + .property("email", codecOptional(codecForString())) + .property("website", codecOptional(codecForString())) + .property("logo", codecOptional(codecForString())) + .property("merchant_pub", codecForString()) + .property("address", codecForLocation()) + .property("jurisdiction", codecForLocation()) + .property("use_stefan", codecForBoolean()) + .property("default_wire_transfer_delay", codecForDuration) + .property("default_pay_delay", codecForDuration) + .property( + "auth", + buildCodecForObject<{ + method: "external" | "token"; + }>() + .property( + "method", + codecForEither( + codecForConstString("token"), + codecForConstString("external"), + ), + ) + .build("TalerMerchantApi.QueryInstancesResponse.auth"), + ) + .build("TalerMerchantApi.QueryInstancesResponse"); + +export const codecForAccountKycRedirects = (): Codec<AccountKycRedirects> => + buildCodecForObject<AccountKycRedirects>() + .property( + "pending_kycs", + codecForList(codecForMerchantAccountKycRedirect()), + ) + .property("timeout_kycs", codecForList(codecForExchangeKycTimeout())) + + .build("TalerMerchantApi.AccountKycRedirects"); + +export const codecForMerchantAccountKycRedirect = + (): Codec<MerchantAccountKycRedirect> => + buildCodecForObject<MerchantAccountKycRedirect>() + .property("kyc_url", codecForURLString()) + .property("aml_status", codecForNumber()) + .property("exchange_url", codecForURLString()) + .property("payto_uri", codecForPaytoString()) + .build("TalerMerchantApi.MerchantAccountKycRedirect"); + +export const codecForExchangeKycTimeout = (): Codec<ExchangeKycTimeout> => + buildCodecForObject<ExchangeKycTimeout>() + .property("exchange_url", codecForURLString()) + .property("exchange_code", codecForNumber()) + .property("exchange_http_status", codecForNumber()) + .build("TalerMerchantApi.ExchangeKycTimeout"); + +export const codecForAccountAddResponse = (): Codec<AccountAddResponse> => + buildCodecForObject<AccountAddResponse>() + .property("h_wire", codecForString()) + .property("salt", codecForString()) + .build("TalerMerchantApi.AccountAddResponse"); + +export const codecForAccountsSummaryResponse = + (): Codec<AccountsSummaryResponse> => + buildCodecForObject<AccountsSummaryResponse>() + .property("accounts", codecForList(codecForBankAccountEntry())) + .build("TalerMerchantApi.AccountsSummaryResponse"); + +export const codecForBankAccountEntry = (): Codec<BankAccountEntry> => + buildCodecForObject<BankAccountEntry>() + .property("payto_uri", codecForPaytoString()) + .property("h_wire", codecForString()) + .property("active", codecOptional(codecForBoolean())) + .build("TalerMerchantApi.BankAccountEntry"); + +export const codecForBankAccountDetail = (): Codec<BankAccountDetail> => + buildCodecForObject<BankAccountDetail>() + .property("payto_uri", codecForPaytoString()) + .property("h_wire", codecForString()) + .property("salt", codecForString()) + .property("credit_facade_url", codecOptional(codecForURLString())) + .property("active", codecOptional(codecForBoolean())) + .build("TalerMerchantApi.BankAccountEntry"); + +export const codecForInventorySummaryResponse = + (): Codec<InventorySummaryResponse> => + buildCodecForObject<InventorySummaryResponse>() + .property("products", codecForList(codecForInventoryEntry())) + .build("TalerMerchantApi.InventorySummaryResponse"); + +export const codecForInventoryEntry = (): Codec<InventoryEntry> => + buildCodecForObject<InventoryEntry>() + .property("product_id", codecForString()) + .property("product_serial", codecForNumber()) + .build("TalerMerchantApi.InventoryEntry"); + +export const codecForMerchantPosProductDetail = + (): Codec<MerchantPosProductDetail> => + buildCodecForObject<MerchantPosProductDetail>() + .property("product_serial", codecForNumber()) + .property("product_id", codecOptional(codecForString())) + .property("categories", codecForList(codecForNumber())) + .property("description", codecForString()) + .property("description_i18n", codecForInternationalizedString()) + .property("unit", codecForString()) + .property("price", codecForAmountString()) + .property("image", codecForString()) + .property("taxes", codecOptional(codecForList(codecForTax()))) + .property("total_stock", codecForNumber()) + .property("minimum_age", codecOptional(codecForNumber())) + .build("TalerMerchantApi.MerchantPosProductDetail"); + +export const codecForMerchantCategory = (): Codec<MerchantCategory> => + buildCodecForObject<MerchantCategory>() + .property("id", codecForNumber()) + .property("name", codecForString()) + .property("name_i18n", codecForInternationalizedString()) + .build("TalerMerchantApi.MerchantCategory"); + +export const codecForFullInventoryDetailsResponse = + (): Codec<FullInventoryDetailsResponse> => + buildCodecForObject<FullInventoryDetailsResponse>() + .property("categories", codecForList(codecForMerchantCategory())) + .property("products", codecForList(codecForMerchantPosProductDetail())) + .build("TalerMerchantApi.FullInventoryDetailsResponse"); + +export const codecForProductDetail = (): Codec<ProductDetail> => + buildCodecForObject<ProductDetail>() + .property("description", codecForString()) + .property("description_i18n", codecForInternationalizedString()) + .property("unit", codecForString()) + .property("price", codecForAmountString()) + .property("image", codecForString()) + .property("taxes", codecOptional(codecForList(codecForTax()))) + .property("address", codecOptional(codecForLocation())) + .property("next_restock", codecOptional(codecForTimestamp)) + .property("total_stock", codecForNumber()) + .property("total_sold", codecForNumber()) + .property("total_lost", codecForNumber()) + .property("minimum_age", codecOptional(codecForNumber())) + .build("TalerMerchantApi.ProductDetail"); + +export const codecForTax = (): Codec<Tax> => + buildCodecForObject<Tax>() + .property("name", codecForString()) + .property("tax", codecForAmountString()) + .build("TalerMerchantApi.Tax"); + +export const codecForPostOrderResponse = (): Codec<PostOrderResponse> => + buildCodecForObject<PostOrderResponse>() + .property("order_id", codecForString()) + .property("token", codecOptional(codecForString())) + .build("TalerMerchantApi.PostOrderResponse"); + +export const codecForOutOfStockResponse = (): Codec<OutOfStockResponse> => + buildCodecForObject<OutOfStockResponse>() + .property("product_id", codecForString()) + .property("available_quantity", codecForNumber()) + .property("requested_quantity", codecForNumber()) + .property("restock_expected", codecForTimestamp) + .build("TalerMerchantApi.OutOfStockResponse"); + +export const codecForOrderHistory = (): Codec<OrderHistory> => + buildCodecForObject<OrderHistory>() + .property("orders", codecForList(codecForOrderHistoryEntry())) + .build("TalerMerchantApi.OrderHistory"); + +export const codecForOrderHistoryEntry = (): Codec<OrderHistoryEntry> => + buildCodecForObject<OrderHistoryEntry>() + .property("order_id", codecForString()) + .property("row_id", codecForNumber()) + .property("timestamp", codecForTimestamp) + .property("amount", codecForAmountString()) + .property("summary", codecForString()) + .property("refundable", codecForBoolean()) + .property("paid", codecForBoolean()) + .build("TalerMerchantApi.OrderHistoryEntry"); + +export const codecForMerchant = (): Codec<Merchant> => + buildCodecForObject<Merchant>() + .property("name", codecForString()) + .property("email", codecOptional(codecForString())) + .property("logo", codecOptional(codecForString())) + .property("website", codecOptional(codecForString())) + .property("address", codecOptional(codecForLocation())) + .property("jurisdiction", codecOptional(codecForLocation())) + .build("TalerMerchantApi.MerchantInfo"); + +export const codecForExchange = (): Codec<Exchange> => + buildCodecForObject<Exchange>() + .property("master_pub", codecForString()) + .property("priority", codecForNumber()) + .property("url", codecForString()) + .build("TalerMerchantApi.Exchange"); + +export const codecForContractTerms = (): Codec<ContractTerms> => + buildCodecForObject<ContractTerms>() + .property("order_id", codecForString()) + .property("fulfillment_url", codecOptional(codecForString())) + .property("fulfillment_message", codecOptional(codecForString())) + .property( + "fulfillment_message_i18n", + codecOptional(codecForInternationalizedString()), + ) + .property("merchant_base_url", codecForString()) + .property("h_wire", codecForString()) + .property("auto_refund", codecOptional(codecForDuration)) + .property("wire_method", codecForString()) + .property("summary", codecForString()) + .property("summary_i18n", codecOptional(codecForInternationalizedString())) + .property("nonce", codecForString()) + .property("amount", codecForAmountString()) + .property("pay_deadline", codecForTimestamp) + .property("refund_deadline", codecForTimestamp) + .property("wire_transfer_deadline", codecForTimestamp) + .property("timestamp", codecForTimestamp) + .property("delivery_location", codecOptional(codecForLocation())) + .property("delivery_date", codecOptional(codecForTimestamp)) + .property("max_fee", codecForAmountString()) + .property("merchant", codecForMerchant()) + .property("merchant_pub", codecForString()) + .property("exchanges", codecForList(codecForExchange())) + .property("products", codecForList(codecForProduct())) + .property("extra", codecForAny()) + .build("TalerMerchantApi.ContractTerms"); + +export const codecForProduct = (): Codec<Product> => + buildCodecForObject<Product>() + .property("product_id", codecOptional(codecForString())) + .property("description", codecForString()) + .property( + "description_i18n", + codecOptional(codecForInternationalizedString()), + ) + .property("quantity", codecOptional(codecForNumber())) + .property("unit", codecOptional(codecForString())) + .property("price", codecOptional(codecForAmountString())) + .property("image", codecOptional(codecForString())) + .property("taxes", codecOptional(codecForList(codecForTax()))) + .property("delivery_date", codecOptional(codecForTimestamp)) + .build("TalerMerchantApi.Product"); + +export const codecForCheckPaymentPaidResponse = + (): Codec<CheckPaymentPaidResponse> => + buildCodecForObject<CheckPaymentPaidResponse>() + .property("order_status", codecForConstString("paid")) + .property("refunded", codecForBoolean()) + .property("refund_pending", codecForBoolean()) + .property("wired", codecForBoolean()) + .property("deposit_total", codecForAmountString()) + .property("exchange_code", codecForNumber()) + .property("exchange_http_status", codecForNumber()) + .property("refund_amount", codecForAmountString()) + .property("contract_terms", codecForContractTerms()) + .property("wire_reports", codecForList(codecForTransactionWireReport())) + .property("wire_details", codecForList(codecForTransactionWireTransfer())) + .property("refund_details", codecForList(codecForRefundDetails())) + .property("order_status_url", codecForURLString()) + .build("TalerMerchantApi.CheckPaymentPaidResponse"); + +export const codecForCheckPaymentUnpaidResponse = + (): Codec<CheckPaymentUnpaidResponse> => + buildCodecForObject<CheckPaymentUnpaidResponse>() + .property("order_status", codecForConstString("unpaid")) + .property("taler_pay_uri", codecForTalerUriString()) + .property("creation_time", codecForTimestamp) + .property("summary", codecForString()) + .property("total_amount", codecForAmountString()) + .property("already_paid_order_id", codecOptional(codecForString())) + .property("already_paid_fulfillment_url", codecOptional(codecForString())) + .property("order_status_url", codecForString()) + .build("TalerMerchantApi.CheckPaymentPaidResponse"); + +export const codecForCheckPaymentClaimedResponse = + (): Codec<CheckPaymentClaimedResponse> => + buildCodecForObject<CheckPaymentClaimedResponse>() + .property("order_status", codecForConstString("claimed")) + .property("contract_terms", codecForContractTerms()) + .build("TalerMerchantApi.CheckPaymentClaimedResponse"); + +export const codecForMerchantOrderPrivateStatusResponse = + (): Codec<MerchantOrderStatusResponse> => + buildCodecForUnion<MerchantOrderStatusResponse>() + .discriminateOn("order_status") + .alternative("paid", codecForCheckPaymentPaidResponse()) + .alternative("unpaid", codecForCheckPaymentUnpaidResponse()) + .alternative("claimed", codecForCheckPaymentClaimedResponse()) + .build("TalerMerchantApi.MerchantOrderStatusResponse"); + +export const codecForRefundDetails = (): Codec<RefundDetails> => + buildCodecForObject<RefundDetails>() + .property("reason", codecForString()) + .property("pending", codecForBoolean()) + .property("timestamp", codecForTimestamp) + .property("amount", codecForAmountString()) + .build("TalerMerchantApi.RefundDetails"); + +export const codecForTransactionWireTransfer = + (): Codec<TransactionWireTransfer> => + buildCodecForObject<TransactionWireTransfer>() + .property("exchange_url", codecForURLString()) + .property("wtid", codecForString()) + .property("execution_time", codecForTimestamp) + .property("amount", codecForAmountString()) + .property("confirmed", codecForBoolean()) + .build("TalerMerchantApi.TransactionWireTransfer"); + +export const codecForTransactionWireReport = (): Codec<TransactionWireReport> => + buildCodecForObject<TransactionWireReport>() + .property("code", codecForNumber()) + .property("hint", codecForString()) + .property("exchange_code", codecForNumber()) + .property("exchange_http_status", codecForNumber()) + .property("coin_pub", codecForString()) + .build("TalerMerchantApi.TransactionWireReport"); + +export const codecForMerchantRefundResponse = + (): Codec<MerchantRefundResponse> => + buildCodecForObject<MerchantRefundResponse>() + .property("taler_refund_uri", codecForTalerUriString()) + .property("h_contract", codecForString()) + .build("TalerMerchantApi.MerchantRefundResponse"); + +export const codecForTansferList = (): Codec<TransferList> => + buildCodecForObject<TransferList>() + .property("transfers", codecForList(codecForTransferDetails())) + .build("TalerMerchantApi.TransferList"); + +export const codecForTransferDetails = (): Codec<TransferDetails> => + buildCodecForObject<TransferDetails>() + .property("credit_amount", codecForAmountString()) + .property("wtid", codecForString()) + .property("payto_uri", codecForPaytoString()) + .property("exchange_url", codecForURLString()) + .property("transfer_serial_id", codecForNumber()) + .property("execution_time", codecOptional(codecForTimestamp)) + .property("verified", codecOptional(codecForBoolean())) + .property("confirmed", codecOptional(codecForBoolean())) + .build("TalerMerchantApi.TransferDetails"); + +export const codecForOtpDeviceSummaryResponse = + (): Codec<OtpDeviceSummaryResponse> => + buildCodecForObject<OtpDeviceSummaryResponse>() + .property("otp_devices", codecForList(codecForOtpDeviceEntry())) + .build("TalerMerchantApi.OtpDeviceSummaryResponse"); + +export const codecForOtpDeviceEntry = (): Codec<OtpDeviceEntry> => + buildCodecForObject<OtpDeviceEntry>() + .property("otp_device_id", codecForString()) + .property("device_description", codecForString()) + .build("TalerMerchantApi.OtpDeviceEntry"); + +export const codecForOtpDeviceDetails = (): Codec<OtpDeviceDetails> => + buildCodecForObject<OtpDeviceDetails>() + .property("device_description", codecForString()) + .property("otp_algorithm", codecForNumber()) + .property("otp_ctr", codecOptional(codecForNumber())) + .property("otp_timestamp", codecForNumber()) + .property("otp_code", codecOptional(codecForString())) + .build("TalerMerchantApi.OtpDeviceDetails"); + +export const codecForTemplateSummaryResponse = + (): Codec<TemplateSummaryResponse> => + buildCodecForObject<TemplateSummaryResponse>() + .property("templates", codecForList(codecForTemplateEntry())) + .build("TalerMerchantApi.TemplateSummaryResponse"); + +export const codecForTemplateEntry = (): Codec<TemplateEntry> => + buildCodecForObject<TemplateEntry>() + .property("template_id", codecForString()) + .property("template_description", codecForString()) + .build("TalerMerchantApi.TemplateEntry"); + +export const codecForTemplateDetails = (): Codec<TemplateDetails> => + buildCodecForObject<TemplateDetails>() + .property("template_description", codecForString()) + .property("otp_id", codecOptional(codecForString())) + .property("template_contract", codecForTemplateContractDetails()) + .property( + "editable_defaults", + codecOptional(codecForTemplateContractDetailsDefaults()), + ) + .build("TalerMerchantApi.TemplateDetails"); + +export const codecForTemplateContractDetails = + (): Codec<TemplateContractDetails> => + buildCodecForObject<TemplateContractDetails>() + .property("summary", codecOptional(codecForString())) + .property("currency", codecOptional(codecForString())) + .property("amount", codecOptional(codecForAmountString())) + .property("minimum_age", codecForNumber()) + .property("pay_duration", codecForDuration) + .build("TalerMerchantApi.TemplateContractDetails"); + +export const codecForTemplateContractDetailsDefaults = + (): Codec<TemplateContractDetailsDefaults> => + buildCodecForObject<TemplateContractDetailsDefaults>() + .property("summary", codecOptional(codecForString())) + .property("currency", codecOptional(codecForString())) + .property("amount", codecOptional(codecForAmountString())) + .build("TalerMerchantApi.TemplateContractDetailsDefaults"); + +export const codecForWalletTemplateDetails = (): Codec<WalletTemplateDetails> => + buildCodecForObject<WalletTemplateDetails>() + .property("template_contract", codecForTemplateContractDetails()) + .property( + "editable_defaults", + codecOptional(codecForTemplateContractDetailsDefaults()), + ) + .build("TalerMerchantApi.WalletTemplateDetails"); + +export const codecForWebhookSummaryResponse = + (): Codec<WebhookSummaryResponse> => + buildCodecForObject<WebhookSummaryResponse>() + .property("webhooks", codecForList(codecForWebhookEntry())) + .build("TalerMerchantApi.WebhookSummaryResponse"); + +export const codecForWebhookEntry = (): Codec<WebhookEntry> => + buildCodecForObject<WebhookEntry>() + .property("webhook_id", codecForString()) + .property("event_type", codecForString()) + .build("TalerMerchantApi.WebhookEntry"); + +export const codecForWebhookDetails = (): Codec<WebhookDetails> => + buildCodecForObject<WebhookDetails>() + .property("event_type", codecForString()) + .property("url", codecForString()) + .property("http_method", codecForString()) + .property("header_template", codecOptional(codecForString())) + .property("body_template", codecOptional(codecForString())) + .build("TalerMerchantApi.WebhookDetails"); + +export const codecForTokenFamilyKind = (): Codec<TokenFamilyKind> => + codecForEither( + codecForConstString("discount"), + codecForConstString("subscription"), + ) as any; //FIXME: create a codecForEnum +export const codecForTokenFamilyDetails = (): Codec<TokenFamilyDetails> => + buildCodecForObject<TokenFamilyDetails>() + .property("slug", codecForString()) + .property("name", codecForString()) + .property("description", codecForString()) + .property("description_i18n", codecForInternationalizedString()) + .property("valid_after", codecForTimestamp) + .property("valid_before", codecForTimestamp) + .property("duration", codecForDuration) + .property("kind", codecForTokenFamilyKind()) + .property("issued", codecForNumber()) + .property("redeemed", codecForNumber()) + .build("TalerMerchantApi.TokenFamilyDetails"); + +export const codecForTokenFamiliesList = (): Codec<TokenFamiliesList> => + buildCodecForObject<TokenFamiliesList>() + .property("token_families", codecForList(codecForTokenFamilySummary())) + .build("TalerMerchantApi.TokenFamiliesList"); + +export const codecForTokenFamilySummary = (): Codec<TokenFamilySummary> => + buildCodecForObject<TokenFamilySummary>() + .property("slug", codecForString()) + .property("name", codecForString()) + .property("valid_after", codecForTimestamp) + .property("valid_before", codecForTimestamp) + .property("kind", codecForTokenFamilyKind()) + .build("TalerMerchantApi.TokenFamilySummary"); + +export const codecForInstancesResponse = (): Codec<InstancesResponse> => + buildCodecForObject<InstancesResponse>() + .property("instances", codecForList(codecForInstance())) + .build("TalerMerchantApi.InstancesResponse"); + +export const codecForInstance = (): Codec<Instance> => + buildCodecForObject<Instance>() + .property("name", codecForString()) + .property("user_type", codecForString()) + .property("website", codecOptional(codecForString())) + .property("logo", codecOptional(codecForString())) + .property("id", codecForString()) + .property("merchant_pub", codecForString()) + .property("payment_targets", codecForList(codecForString())) + .property("deleted", codecForBoolean()) + .build("TalerMerchantApi.Instance"); + +export const codecForTemplateEditableDetails = + (): Codec<TemplateEditableDetails> => + buildCodecForObject<TemplateEditableDetails>() + .property("summary", codecOptional(codecForString())) + .property("currency", codecOptional(codecForString())) + .property("amount", codecOptional(codecForAmountString())) + .build("TemplateEditableDetails"); + +export const codecForMerchantReserveCreateConfirmation = + (): Codec<MerchantReserveCreateConfirmation> => + buildCodecForObject<MerchantReserveCreateConfirmation>() + .property("accounts", codecForList(codecForExchangeWireAccount())) + .property("reserve_pub", codecForString()) + .build("MerchantReserveCreateConfirmation"); diff --git a/packages/taler-util/src/types-taler-revenue.ts b/packages/taler-util/src/types-taler-revenue.ts @@ -0,0 +1,95 @@ +/* + This file is part of GNU Taler + (C) 2024 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero 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 Affero General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + + SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { codecForAmountString } from "./amounts.js"; +import { Codec, buildCodecForObject, codecForConstString, codecForList, codecForNumber, codecForString, codecOptional } from "./codec.js"; +import { codecForPaytoString } from "./payto.js"; +import { codecForTimestamp } from "./time.js"; +import { AmountString, SafeUint64, Timestamp } from "./types-taler-common.js"; + +export interface RevenueConfig { + // Name of the API. + name: "taler-revenue"; + + // libtool-style representation of the Bank protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Currency used by this gateway. + currency: string; + + // URN of the implementation (needed to interpret 'revision' in version). + // @since v0, may become mandatory in the future. + implementation?: string; +} + +export interface RevenueIncomingHistory { + // Array of incoming transactions. + incoming_transactions: RevenueIncomingBankTransaction[]; + + // Payto URI to identify the receiver of funds. + // Credit account is shared by all incoming transactions + // as per the nature of the request. + credit_account: string; +} + +export interface RevenueIncomingBankTransaction { + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Date of the transaction. + date: Timestamp; + + // Amount transferred. + amount: AmountString; + + // Payto URI to identify the sender of funds. + debit_account: string; + + // The wire transfer subject. + subject: string; +} + +export const codecForRevenueConfig = (): Codec<RevenueConfig> => + buildCodecForObject<RevenueConfig>() + .property("name", codecForConstString("taler-revenue")) + .property("version", codecForString()) + .property("currency", codecForString()) + .property("implementation", codecOptional(codecForString())) + .build("TalerRevenueApi.RevenueConfig"); + +export const codecForRevenueIncomingHistory = + (): Codec<RevenueIncomingHistory> => + buildCodecForObject<RevenueIncomingHistory>() + .property("credit_account", codecForPaytoString()) + .property( + "incoming_transactions", + codecForList(codecForRevenueIncomingBankTransaction()), + ) + .build("TalerRevenueApi.MerchantIncomingHistory"); + +export const codecForRevenueIncomingBankTransaction = + (): Codec<RevenueIncomingBankTransaction> => + buildCodecForObject<RevenueIncomingBankTransaction>() + .property("amount", codecForAmountString()) + .property("date", codecForTimestamp) + .property("debit_account", codecForPaytoString()) + .property("row_id", codecForNumber()) + .property("subject", codecForString()) + .build("TalerRevenueApi.RevenueIncomingBankTransaction");