From b5312973a6f25ac73c8e29b659bf7ea23d77ac5e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 18 Mar 2024 12:12:57 -0300 Subject: wip --- packages/taler-util/src/http-client/README.md | 24 + packages/taler-util/src/http-client/merchant.ts | 679 ++++++++++++++++++++++++ packages/taler-util/src/http-client/types.ts | 106 ++-- 3 files changed, 771 insertions(+), 38 deletions(-) create mode 100644 packages/taler-util/src/http-client/README.md create mode 100644 packages/taler-util/src/http-client/merchant.ts (limited to 'packages/taler-util/src') diff --git a/packages/taler-util/src/http-client/README.md b/packages/taler-util/src/http-client/README.md new file mode 100644 index 000000000..5af5d48a7 --- /dev/null +++ b/packages/taler-util/src/http-client/README.md @@ -0,0 +1,24 @@ +HTTP Cclients +------------- + +This folder contain class or function specifically designed to facilitate HTTP client +interactions with a the core systems. + +These API defines: + +1. **API Communication**: Handle communication with the component API, +abstracting away the details of HTTP requests and responses. +This includes making GET, POST, PUT, and DELETE requests to the servers. + +2. **Data Formatting**: Responsible for formatting requests to the API in a +way that's expected by the servers (JSON) and parsing the responses back +into formats usable by the client. + +3. **Authentication and Security**: Handling authentication with the server API, +which could involve sending API keys, client credentials, or managing tokens. +It might also implement security features to ensure data integrity and confidentiality during transit. + +4. **Error Handling**: Providing robust error handling and retry mechanisms +for failed HTTP requests, including logging and potentially user notifications for critical failures. + +5. **Data Validation**: Before sending requests, it could validate the data to ensure it meets the API's expected format, types, and value ranges, reducing the likelihood of errors and improving system reliability. diff --git a/packages/taler-util/src/http-client/merchant.ts b/packages/taler-util/src/http-client/merchant.ts new file mode 100644 index 000000000..32384f8b4 --- /dev/null +++ b/packages/taler-util/src/http-client/merchant.ts @@ -0,0 +1,679 @@ +/* + This file is part of GNU Taler + (C) 2022-2024 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 + */ + +import { + HttpStatusCode, + LibtoolVersion, + MerchantApiClient, + TalerMerchantApi, + codecForMerchantConfig +} from "@gnu-taler/taler-util"; +import { + HttpRequestLibrary, + createPlatformHttpLib, +} from "@gnu-taler/taler-util/http"; +import { + FailCasesByMethod, + ResultByMethod, + opSuccessFromHttp, + opUnknownFailure, +} from "../operation.js"; +import { CacheEvictor, nullEvictor } from "./utils.js"; + +export enum TalerMerchantCacheEviction { + CREATE_ORDER, +} +/** + * Protocol version spoken with the core bank. + * + * Endpoint must be ordered in the same way that in the docs + * Response code (http and taler) must have the same order that in the docs + * That way is easier to see changes + * + * Uses libtool's current:revision:age versioning. + */ +class TalerMerchantInstanceHttpClient { + + readonly httpLib: HttpRequestLibrary; + readonly cacheEvictor: CacheEvictor; + + constructor( + readonly baseUrl: string, + httpClient?: HttpRequestLibrary, + cacheEvictor?: CacheEvictor, + ) { + this.httpLib = httpClient ?? createPlatformHttpLib(); + this.cacheEvictor = cacheEvictor ?? nullEvictor; + } + + // + // Wallet API + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-claim + */ + async claimOrder(orderId: string, body: TalerMerchantApi.ClaimRequest) { + const url = new URL(`orders/${orderId}/claim`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + // switch (resp.status) { + // case HttpStatusCode.Ok: + // return opSuccessFromHttp(resp, codecForClaimResponse()); + // case HttpStatusCode.Conflict: + // return opKnownHttpFailure(resp.status, resp) + // case HttpStatusCode.NotFound: + // return opKnownHttpFailure(resp.status, resp) + // default: + // return opUnknownFailure(resp, await resp.text()); + // } + } + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-pay + */ + async makePayment(orderId: string, body: TalerMerchantApi.PayRequest) { + const url = new URL(`orders/${orderId}/pay`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + /// + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-orders-$ORDER_ID + */ + + async getPaymentStatus(orderId: string, params: TalerMerchantApi.PaymentStatusRequestParams = {}) { + const url = new URL(`orders/${orderId}`, this.baseUrl); + + if (params.allowRefundedForRepurchase !== undefined) { + url.searchParams.set("allow_refunded_for_repurchase", params.allowRefundedForRepurchase ? "YES" : "NO") + } + if (params.awaitRefundObtained !== undefined) { + url.searchParams.set("await_refund_obtained", params.allowRefundedForRepurchase ? "YES" : "NO") + } + if (params.claimToken !== undefined) { + url.searchParams.set("token", params.claimToken) + } + if (params.contractTermHash !== undefined) { + url.searchParams.set("h_contract", params.contractTermHash) + } + if (params.refund !== undefined) { + url.searchParams.set("refund", params.refund) + } + if (params.sessionId !== undefined) { + url.searchParams.set("session_id", params.sessionId) + } + if (params.timeout !== undefined) { + url.searchParams.set("timeout_ms", String(params.timeout)) + } + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + // body, + }); + + /// + } + + /** + * https://docs.taler.net/core/api-merchant.html#demonstrating-payment + */ + async demostratePayment(orderId: string, body: TalerMerchantApi.PaidRequest) { + const url = new URL(`orders/${orderId}/paid`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#aborting-incomplete-payments + */ + async abortIncompletePayment(orderId: string, body: TalerMerchantApi.AbortRequest) { + const url = new URL(`orders/${orderId}/abort`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#obtaining-refunds + */ + async obtainRefund(orderId: string, body: TalerMerchantApi.WalletRefundRequest) { + const url = new URL(`orders/${orderId}/refund`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + // + // Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-auth + */ + async updateCurrentInstanceAuthentication(body: TalerMerchantApi.InstanceAuthConfigurationMessage) { + const url = new URL(`private/auth`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + /** + * Get the auth api agaisnt the current instance + * + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-token + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-token + */ + getAuthenticationAPI(): URL { + return new URL(`/`, this.baseUrl); + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private + */ + async updateCurrentInstance(body: TalerMerchantApi.InstanceReconfigurationMessage) { + const url = new URL(`private`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "PATCH", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private + * + */ + async getCurrentInstance() { + const url = new URL(`private`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private + */ + async deleteCurrentInstance(params: { purge?: boolean }) { + const url = new URL(`private`, this.baseUrl); + + if (params.purge) { + url.searchParams.set("purge", "YES") + } + + const resp = await this.httpLib.fetch(url.href, { + method: "DELETE", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--instances-$INSTANCE-private-kyc + */ + async getCurrentIntanceKycStatus(params: { wireHash?: string, exchangeURL?: string, timeout: number }) { + const url = new URL(`private/kyc`, this.baseUrl); + + if (params.wireHash) { + url.searchParams.set("h_wire", params.wireHash) + } + if (params.exchangeURL) { + url.searchParams.set("exchange_url", params.exchangeURL) + } + if (params.timeout) { + url.searchParams.set("timeout_ms", String(params.timeout)) + } + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + + } + + // + // Bank Accounts + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-accounts + */ + async addAccount(body: TalerMerchantApi.AccountAddDetails) { + const url = new URL(`private/accounts`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async updateAccount(wireAccount: string, body: TalerMerchantApi.AccountPatchDetails) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "PATCH", + body, + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts + */ + async listAccounts() { + const url = new URL(`private/accounts`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async getAccount(wireAccount: string) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-accounts-$H_WIRE + */ + async deleteAccount(wireAccount: string) { + const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "DELETE", + }); + } + + // + // Inventory Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-products + */ + async addProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-products-$PRODUCT_ID + */ + async updateProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products + */ + async listProducts() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products-$PRODUCT_ID + */ + async getProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#reserving-inventory + */ + async lockProduct() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#removing-products-from-inventory + */ + async removeProduct() { + } + + // + // Payment processing + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders + */ + async createOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#inspecting-orders + */ + async listOrders() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders-$ORDER_ID + */ + async getOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#private-order-data-cleanup + */ + async forgetOrder() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-orders-$ORDER_ID + */ + async deleteOrder() { + } + + // + // Refunds + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders-$ORDER_ID-refund + */ + async addRefund() { + } + + // + // Wire Transfer + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-transfers + */ + async informWireTransfer() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-transfers + */ + async listWireTransfers() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-transfers-$TID + */ + async deleteWireTransfer() { + } + + // + // OTP Devices + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-otp-devices + */ + async addOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async updateOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices + */ + async listOtpDevices() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async getOtpDevice() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID + */ + async deleteOtpDevice() { + } + + // + // Templates + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-templates + */ + async addTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async updateTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#inspecting-template + */ + async listTemplates() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async getTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID + */ + async deleteTemplate() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-templates-$TEMPLATE_ID + */ + async useTemplate() { + } + + // + // Webhooks + // + + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-webhooks + */ + async addWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async updateWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks + */ + async listWebhooks() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async getWebhook() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID + */ + async removeWebhook() { + } + + // + // token families + // + + /** + * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-tokenfamilies + */ + async createTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async updateTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies + */ + async listTokenFamilies() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async getTokenFamily() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG + */ + async deleteTokenFamily() { + } + +} + +export class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttpClient { + public readonly PROTOCOL_VERSION = "10:0:6"; + + httpLib: HttpRequestLibrary; + cacheEvictor: CacheEvictor; + constructor( + readonly baseUrl: string, + httpClient?: HttpRequestLibrary, + cacheEvictor?: CacheEvictor, + ) { + super(baseUrl, httpClient, cacheEvictor) + } + + isCompatible(version: string): boolean { + const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version); + return compare?.compatible ?? false; + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--config + * + */ + async getConfig() { + const url = new URL(`config`, this.baseUrl); + const resp = await this.httpLib.fetch(url.href, { + method: "GET", + }); + switch (resp.status) { + case HttpStatusCode.Ok: + return opSuccessFromHttp(resp, codecForMerchantConfig()); + default: + return opUnknownFailure(resp, await resp.text()); + } + } + + + // + // Instance Management + // + + /** + * https://docs.taler.net/core/api-merchant.html#post--management-instances + */ + async createInstance(body: TalerMerchantApi.InstanceConfigurationMessage) { + const url = new URL(`management/instances`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + /** + * https://docs.taler.net/core/api-merchant.html#post--management-instances-$INSTANCE-auth + */ + async updateInstanceAuthentication(body: TalerMerchantApi.InstanceAuthConfigurationMessage) { + const url = new URL(`management/instances`, this.baseUrl); + + const resp = await this.httpLib.fetch(url.href, { + method: "POST", + body, + }); + + // + } + + + /** + * https://docs.taler.net/core/api-merchant.html#patch--management-instances-$INSTANCE + */ + async updateInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances + */ + async listInstances() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE + * + */ + async getInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#delete--management-instances-$INSTANCE + */ + async deleteInstance() { + } + + /** + * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-kyc + */ + async getIntanceKycStatus() { + } + + + + +} diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index 132ca867d..08b29106e 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -2403,6 +2403,10 @@ export namespace TalerMerchantApi { // 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 @@ -2417,8 +2421,27 @@ export namespace TalerMerchantApi { // All currencies in this map are supported by // the backend. 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; @@ -2447,7 +2470,43 @@ export namespace TalerMerchantApi { pos_confirmation?: string; } - interface PayRequest { + 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 PayRequest { // The coins used to make the payment. coins: CoinPaySig[]; @@ -2520,7 +2579,7 @@ export namespace TalerMerchantApi { // refunds. False if it was simply paid. refunded: boolean; } - interface PaidRequest { + export interface PaidRequest { // Signature on TALER_PaymentResponsePS with the public // key of the merchant instance. sig: EddsaSignature; @@ -2537,7 +2596,7 @@ export namespace TalerMerchantApi { session_id: string; } - interface AbortRequest { + 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; @@ -2603,7 +2662,7 @@ export namespace TalerMerchantApi { exchange_pub: EddsaPublicKey; } - interface WalletRefundRequest { + export interface WalletRefundRequest { // Hash of the order's contract terms (this is used to authenticate the // wallet/customer). h_contract: HashCode; @@ -2723,7 +2782,7 @@ export namespace TalerMerchantApi { blind_sig: BlindedRsaSignature; } - interface InstanceConfigurationMessage { + 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; @@ -2771,7 +2830,7 @@ export namespace TalerMerchantApi { default_pay_delay: RelativeTime; } - interface InstanceAuthConfigurationMessage { + export interface InstanceAuthConfigurationMessage { // Type of authentication. // "external": The mechant backend does not do // any authentication checks. Instead an API @@ -2788,37 +2847,8 @@ export namespace TalerMerchantApi { token?: string; } - interface LoginTokenRequest { - // Scope of the token (which kinds of operations it will allow) - scope: "readonly" | "write"; - - // Server may impose its own upper bound - // on the token validity duration - duration?: RelativeTime; - - // Can this token be refreshed? - // Defaults to false. - refreshable?: boolean; - } - interface LoginTokenSuccessResponse { - // The login token that can be used to access resources - // that are in scope for some time. Must be prefixed - // with "Bearer " when used in the "Authorization" HTTP header. - // Will already begin with the RFC 8959 prefix. - token: string; - - // Scope of the token (which kinds of operations it will allow) - scope: "readonly" | "write"; - - // Server may impose its own upper bound - // on the token validity duration - expiration: Timestamp; - - // Can this token be refreshed? - refreshable: boolean; - } - interface InstanceReconfigurationMessage { + export interface InstanceReconfigurationMessage { // Merchant name corresponding to this instance. name: string; @@ -2980,7 +3010,7 @@ export namespace TalerMerchantApi { exchange_http_status: number; } - interface AccountAddDetails { + export interface AccountAddDetails { // payto:// URI of the account. payto_uri: PaytoString; @@ -3017,7 +3047,7 @@ export namespace TalerMerchantApi { salt: HashCode; } - interface AccountPatchDetails { + export interface AccountPatchDetails { // URL from where the merchant can download information // about incoming wire transfers to this account. credit_facade_url?: string; -- cgit v1.2.3