diff options
Diffstat (limited to 'packages/taler-util')
-rw-r--r-- | packages/taler-util/src/MerchantApiClient.ts | 21 | ||||
-rw-r--r-- | packages/taler-util/src/http-client/types.ts | 96 | ||||
-rw-r--r-- | packages/taler-util/src/index.ts | 9 | ||||
-rw-r--r-- | packages/taler-util/src/merchant-api-types.ts | 352 | ||||
-rw-r--r-- | packages/taler-util/src/taler-types.ts | 6 | ||||
-rw-r--r-- | packages/taler-util/src/taleruri.test.ts | 11 | ||||
-rw-r--r-- | packages/taler-util/src/taleruri.ts | 5 | ||||
-rw-r--r-- | packages/taler-util/src/wallet-types.ts | 10 |
8 files changed, 116 insertions, 394 deletions
diff --git a/packages/taler-util/src/MerchantApiClient.ts b/packages/taler-util/src/MerchantApiClient.ts index c27f1d582..f58757fb5 100644 --- a/packages/taler-util/src/MerchantApiClient.ts +++ b/packages/taler-util/src/MerchantApiClient.ts @@ -19,6 +19,7 @@ import { TalerMerchantApi, codecForMerchantConfig, codecForMerchantOrderPrivateStatusResponse, + codecForPostOrderResponse, } from "./http-client/types.js"; import { HttpStatusCode } from "./http-status-codes.js"; import { @@ -31,13 +32,6 @@ import { FacadeCredentials } from "./libeufin-api-types.js"; import { LibtoolVersion } from "./libtool-version.js"; import { Logger } from "./logging.js"; import { - MerchantInstancesResponse, - MerchantPostOrderRequest, - MerchantPostOrderResponse, - MerchantTemplateAddDetails, - codecForMerchantPostOrderResponse, -} from "./merchant-api-types.js"; -import { FailCasesByMethod, OperationFail, OperationOk, @@ -206,7 +200,7 @@ export class MerchantApiClient { }); } - async getInstances(): Promise<MerchantInstancesResponse> { + async getInstances(): Promise<TalerMerchantApi.InstancesResponse> { const url = new URL("management/instances", this.baseUrl); const resp = await this.httpClient.fetch(url.href, { headers: this.makeAuthHeader(), @@ -227,18 +221,15 @@ export class MerchantApiClient { } async createOrder( - req: MerchantPostOrderRequest, - ): Promise<MerchantPostOrderResponse> { + req: TalerMerchantApi.PostOrderRequest, + ): Promise<TalerMerchantApi.PostOrderResponse> { let url = new URL("private/orders", this.baseUrl); const resp = await this.httpClient.fetch(url.href, { method: "POST", body: req, headers: this.makeAuthHeader(), }); - return readSuccessResponseJsonOrThrow( - resp, - codecForMerchantPostOrderResponse(), - ); + return readSuccessResponseJsonOrThrow(resp, codecForPostOrderResponse()); } async deleteOrder(req: { orderId: string; force?: boolean }): Promise<void> { @@ -292,7 +283,7 @@ export class MerchantApiClient { }; } - async createTemplate(req: MerchantTemplateAddDetails) { + async createTemplate(req: TalerMerchantApi.MerchantTemplateAddDetails) { let url = new URL("private/templates", this.baseUrl); const resp = await this.httpClient.fetch(url.href, { method: "POST", diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index fe8a2ff51..dd95709f9 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -1,4 +1,3 @@ -import { deprecate } from "util"; import { codecForAmountString } from "../amounts.js"; import { Codec, @@ -18,7 +17,9 @@ import { import { PaytoString, codecForPaytoString } from "../payto.js"; import { AmountString, + ExchangeWireAccount, InternationalizedString, + codecForExchangeWireAccount, codecForInternationalizedString, codecForLocation, } from "../taler-types.js"; @@ -27,7 +28,6 @@ import { AbsoluteTime, TalerProtocolDuration, TalerProtocolTimestamp, - codecForAbsoluteTime, codecForDuration, codecForTimestamp, } from "../time.js"; @@ -925,7 +925,6 @@ export const codecForTemplateContractDetailsDefaults = .property("currency", codecOptional(codecForString())) .property("amount", codecOptional(codecForAmountString())) .property("minimum_age", codecOptional(codecForNumber())) - .property("pay_duration", codecOptional(codecForDuration)) .build("TalerMerchantApi.TemplateContractDetailsDefaults"); export const codecForWalletTemplateDetails = @@ -1618,6 +1617,21 @@ export const codecForChallengerInfoResponse = .property("expires", codecForTimestamp) .build("ChallengerApi.ChallengerInfoResponse"); +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 EmailAddress = string; type PhoneNumber = string; type EddsaSignature = string; @@ -4258,9 +4272,9 @@ export namespace TalerMerchantApi { otp_id?: string; } - type Order = MinimalOrderDetail | ContractTerms; + export type Order = MinimalOrderDetail & Partial<ContractTerms>; - interface MinimalOrderDetail { + export interface MinimalOrderDetail { // Amount to be paid by the customer. amount: AmountString; @@ -4279,7 +4293,7 @@ export namespace TalerMerchantApi { fulfillment_message?: string; } - interface MinimalInventoryProduct { + export interface MinimalInventoryProduct { // Which product is requested (here mandatory!). product_id: string; @@ -4719,12 +4733,14 @@ export namespace TalerMerchantApi { currency?: string; - amount?: AmountString; + /** + * Amount *or* a plain currency string. + */ + amount?: string; minimum_age?: Integer; - - pay_duration?: RelativeTime; } + export interface TemplatePatchDetails { // Human-readable description for the template. template_description: string; @@ -5250,6 +5266,68 @@ export namespace TalerMerchantApi { // 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 namespace ChallengerApi { diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts index 24d6e9950..9f99f2f5a 100644 --- a/packages/taler-util/src/index.ts +++ b/packages/taler-util/src/index.ts @@ -18,18 +18,18 @@ export * from "./contract-terms.js"; export * from "./errors.js"; export { fnutil } from "./fnutils.js"; export * from "./helpers.js"; -export * from "./http-client/bank-conversion.js"; export * from "./http-client/authentication.js"; +export * from "./http-client/bank-conversion.js"; export * from "./http-client/bank-core.js"; -export * from "./http-client/merchant.js"; -export * from "./http-client/challenger.js"; export * from "./http-client/bank-integration.js"; export * from "./http-client/bank-revenue.js"; export * from "./http-client/bank-wire.js"; +export * from "./http-client/challenger.js"; export * from "./http-client/exchange.js"; -export { CacheEvictor } from "./http-client/utils.js"; +export * from "./http-client/merchant.js"; export * from "./http-client/officer-account.js"; export * from "./http-client/types.js"; +export { CacheEvictor } from "./http-client/utils.js"; export * from "./http-status-codes.js"; export * from "./i18n.js"; export * from "./iban.js"; @@ -38,7 +38,6 @@ export * from "./kdf.js"; export * from "./libeufin-api-types.js"; export * from "./libtool-version.js"; export * from "./logging.js"; -export * from "./merchant-api-types.js"; export { crypto_sign_keyPair_fromSeed, randomBytes, diff --git a/packages/taler-util/src/merchant-api-types.ts b/packages/taler-util/src/merchant-api-types.ts deleted file mode 100644 index 639ae8d13..000000000 --- a/packages/taler-util/src/merchant-api-types.ts +++ /dev/null @@ -1,352 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2020 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/> - */ - -/** - * Test harness for various GNU Taler components. - * Also provides a fault-injection proxy. - * - * @author Florian Dold <dold@taler.net> - */ - -/** - * Imports. - */ -import { - AbsoluteTime, - AmountString, - Codec, - CoinPublicKeyString, - EddsaPublicKeyString, - ExchangeWireAccount, - FacadeCredentials, - MerchantContractTerms, - TalerProtocolDuration, - TalerProtocolTimestamp, - buildCodecForObject, - buildCodecForUnion, - codecForAmountString, - codecForAny, - codecForBoolean, - codecForCheckPaymentClaimedResponse, - codecForCheckPaymentUnpaidResponse, - codecForConstString, - codecForExchangeWireAccount, - codecForList, - codecForMerchantContractTerms, - codecForNumber, - codecForString, - codecForTimestamp, - codecOptional, -} from "@gnu-taler/taler-util"; - -export interface MerchantPostOrderRequest { - // The order must at least contain the minimal - // order detail, but can override all - order: Partial<MerchantContractTerms>; - - // if set, the backend will then set the refund deadline to the current - // time plus the specified delay. - refund_delay?: TalerProtocolDuration; - - // 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; - - // FIXME: some fields are missing - - // 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; -} - -export type ClaimToken = string; - -export interface MerchantPostOrderResponse { - order_id: string; - token?: ClaimToken; -} - -export const codecForMerchantPostOrderResponse = - (): Codec<MerchantPostOrderResponse> => - buildCodecForObject<MerchantPostOrderResponse>() - .property("order_id", codecForString()) - .property("token", codecOptional(codecForString())) - .build("PostOrderResponse"); - -export const codecForMerchantRefundDetails = (): Codec<RefundDetails> => - buildCodecForObject<RefundDetails>() - .property("reason", codecForString()) - .property("pending", codecForBoolean()) - .property("amount", codecForAmountString()) - .property("timestamp", codecForTimestamp) - .build("PostOrderResponse"); - -export const codecForMerchantCheckPaymentPaidResponse = - (): Codec<MerchantCheckPaymentPaidResponse> => - buildCodecForObject<MerchantCheckPaymentPaidResponse>() - .property("order_status_url", codecForString()) - .property("order_status", codecForConstString("paid")) - .property("refunded", codecForBoolean()) - .property("wired", codecForBoolean()) - .property("deposit_total", codecForAmountString()) - .property("exchange_ec", codecForNumber()) - .property("exchange_hc", codecForNumber()) - .property("refund_amount", codecForAmountString()) - .property("contract_terms", codecForMerchantContractTerms()) - // FIXME: specify - .property("wire_details", codecForAny()) - .property("wire_reports", codecForAny()) - .property("refund_details", codecForAny()) - .build("CheckPaymentPaidResponse"); - -export type MerchantOrderPrivateStatusResponse = - | MerchantCheckPaymentPaidResponse - | CheckPaymentUnpaidResponse - | CheckPaymentClaimedResponse; - -export interface CheckPaymentClaimedResponse { - // Wallet claimed the order, but didn't pay yet. - order_status: "claimed"; - - contract_terms: MerchantContractTerms; -} - -export interface MerchantCheckPaymentPaidResponse { - // did the customer pay for this contract - order_status: "paid"; - - // Was the payment refunded (even partially) - refunded: 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_ec: number; - - // HTTP status code returned by the exchange when we asked for - // information to track the wire transfer for this purchase. - // 0 if there were no issues. - exchange_hc: number; - - // Total amount that was refunded, 0 if refunded is false. - refund_amount: AmountString; - - // Contract terms - contract_terms: MerchantContractTerms; - - // Ihe 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[]; - - order_status_url: string; -} - -export interface CheckPaymentUnpaidResponse { - order_status: "unpaid"; - - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; - - order_status_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; - - // 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; - - // when was the refund approved - timestamp: TalerProtocolTimestamp; - - // has not been taken yet - pending: boolean; - - // 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: string; - - // execution time of the wire transfer - execution_time: AbsoluteTime; - - // 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_ec: number; - - // HTTP status code received from the exchange. - exchange_hc: number; - - // Public key of the coin for which we got the exchange error. - coin_pub: CoinPublicKeyString; -} - -export interface ReserveStatusEntry { - // Public key of the reserve - reserve_pub: string; - - // Timestamp when it was established - creation_time: AbsoluteTime; - - // Timestamp when it expires - expiration_time: AbsoluteTime; - - // Initial amount as per reserve creation call - merchant_initial_amount: AmountString; - - // Initial amount as per exchange, 0 if exchange did - // not confirm reserve creation yet. - exchange_initial_amount: AmountString; - - // Amount picked up so far. - pickup_amount: AmountString; - - // Amount approved for tips that exceeds the pickup_amount. - committed_amount: AmountString; - - // Is this reserve active (false if it was deleted but not purged) - active: boolean; -} - -export interface MerchantInstancesResponse { - // List of instances that are present in the backend (see Instance) - instances: MerchantInstanceDetail[]; -} - -export interface MerchantInstanceDetail { - // Merchant name corresponding to this instance. - name: string; - - // Merchant instance this response is about ($INSTANCE) - id: string; - - // Public key of the merchant/instance, in Crockford Base32 encoding. - merchant_pub: EddsaPublicKeyString; - - // 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[]; -} - -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; - - // Additional information in a separate template. - template_contract: MerchantTemplateContractDetails; - - // OTP device ID. - // This parameter is optional. - otp_id?: string; -} - -export interface MerchantReserveCreateConfirmation { - // Public key identifying the reserve. - reserve_pub: EddsaPublicKeyString; - - // Wire accounts of the exchange where to transfer the funds. - accounts: ExchangeWireAccount[]; -} - -export const codecForMerchantReserveCreateConfirmation = - (): Codec<MerchantReserveCreateConfirmation> => - buildCodecForObject<MerchantReserveCreateConfirmation>() - .property("accounts", codecForList(codecForExchangeWireAccount())) - .property("reserve_pub", codecForString()) - .build("MerchantReserveCreateConfirmation"); - -export interface AccountAddDetails { - // payto:// URI of the account. - payto_uri: string; - - // URL from where the merchant can download information - // about incoming wire transfers to this account. - credit_facade_url?: string; - - // Credentials to use when accessing the credit facade. - // Never returned on a GET (as this may be somewhat - // sensitive data). Can be set in POST - // or PATCH requests to update (or delete) credentials. - // To really delete credentials, set them to the type: "none". - credit_facade_credentials?: FacadeCredentials; -} diff --git a/packages/taler-util/src/taler-types.ts b/packages/taler-util/src/taler-types.ts index 392e7149c..e2536b74a 100644 --- a/packages/taler-util/src/taler-types.ts +++ b/packages/taler-util/src/taler-types.ts @@ -1329,8 +1329,12 @@ export const codecForDenominationPubKey = () => .alternative(DenomKeyType.ClauseSchnorr, codecForCsDenominationPubKey()) .build("DenominationPubKey"); +export type LitAmountString = `${string}:${number}`; + declare const __amount_str: unique symbol; -export type AmountString = string & { [__amount_str]: true }; +export type AmountString = + | (string & { [__amount_str]: true }) + | LitAmountString; // export type AmountString = string; export type Base32String = string; export type EddsaSignatureString = string; diff --git a/packages/taler-util/src/taleruri.test.ts b/packages/taler-util/src/taleruri.test.ts index b751efa34..b92366fb3 100644 --- a/packages/taler-util/src/taleruri.test.ts +++ b/packages/taler-util/src/taleruri.test.ts @@ -314,7 +314,7 @@ test("taler peer to peer pull URI (stringify)", (t) => { test("taler pay template URI (parsing)", (t) => { const url1 = - "taler://pay-template/merchant.example.com/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY?amount=KUDOS:5"; + "taler://pay-template/merchant.example.com/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY"; const r1 = parsePayTemplateUri(url1); if (!r1) { t.fail(); @@ -322,12 +322,11 @@ test("taler pay template URI (parsing)", (t) => { } t.deepEqual(r1.merchantBaseUrl, "https://merchant.example.com/"); t.deepEqual(r1.templateId, "FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY"); - t.deepEqual(r1.templateParams.amount, "KUDOS:5"); }); test("taler pay template URI (parsing, http with port)", (t) => { const url1 = - "taler+http://pay-template/merchant.example.com:1234/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY?amount=KUDOS:5"; + "taler+http://pay-template/merchant.example.com:1234/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY"; const r1 = parsePayTemplateUri(url1); if (!r1) { t.fail(); @@ -335,20 +334,16 @@ test("taler pay template URI (parsing, http with port)", (t) => { } t.deepEqual(r1.merchantBaseUrl, "http://merchant.example.com:1234/"); t.deepEqual(r1.templateId, "FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY"); - t.deepEqual(r1.templateParams.amount, "KUDOS:5"); }); test("taler pay template URI (stringify)", (t) => { const url1 = stringifyPayTemplateUri({ merchantBaseUrl: "http://merchant.example.com:1234/", templateId: "FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY", - templateParams: { - amount: "KUDOS:5", - }, }); t.deepEqual( url1, - "taler+http://pay-template/merchant.example.com:1234/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY?amount=KUDOS%3A5", + "taler+http://pay-template/merchant.example.com:1234/FEGHYJY48FEGU6WETYIOIDEDE2QW3OCZVY", ); }); diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts index 576736503..54b7525e3 100644 --- a/packages/taler-util/src/taleruri.ts +++ b/packages/taler-util/src/taleruri.ts @@ -83,7 +83,6 @@ export interface PayTemplateUriResult { type: TalerUriAction.PayTemplate; merchantBaseUrl: string; templateId: string; - templateParams: TemplateParams; } export interface WithdrawUriResult { @@ -437,7 +436,6 @@ export function parsePayTemplateUri( type: TalerUriAction.PayTemplate, merchantBaseUrl, templateId, - templateParams: params, }; } @@ -668,9 +666,8 @@ export function stringifyDevExperimentUri({ export function stringifyPayTemplateUri({ merchantBaseUrl, templateId, - templateParams, }: Omit<PayTemplateUriResult, "type">): string { - const { proto, path, query } = getUrlInfo(merchantBaseUrl, templateParams); + const { proto, path, query } = getUrlInfo(merchantBaseUrl); return `${proto}://pay-template/${path}${templateId}${query}`; } diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 4e2e08a8b..310ca858e 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -2031,6 +2031,16 @@ export const codecForSharePaymentResult = (): Codec<SharePaymentResult> => .property("privatePayUri", codecForString()) .build("SharePaymentResult"); +export interface CheckPayTemplateRequest { + talerPayTemplateUri: string; +} + +export const codecForCheckPayTemplateRequest = + (): Codec<CheckPayTemplateRequest> => + buildCodecForObject<CheckPayTemplateRequest>() + .property("talerPayTemplateUri", codecForString()) + .build("CheckPayTemplateRequest"); + export interface PreparePayTemplateRequest { talerPayTemplateUri: string; templateParams?: TemplateParams; |