diff options
| -rw-r--r-- | packages/taler-util/src/http-client/bank-core.ts (renamed from packages/taler-util/src/http-client/core-bank.ts) | 52 | ||||
| -rw-r--r-- | packages/taler-util/src/http-client/bank-integration.ts | 44 | ||||
| -rw-r--r-- | packages/taler-util/src/http-client/bank-revenue.ts | 32 | ||||
| -rw-r--r-- | packages/taler-util/src/http-client/bank-wire.ts | 98 | ||||
| -rw-r--r-- | packages/taler-util/src/http-client/types.ts | 592 | ||||
| -rw-r--r-- | packages/taler-util/src/http-client/utils.ts | 12 | 
6 files changed, 728 insertions, 102 deletions
diff --git a/packages/taler-util/src/http-client/core-bank.ts b/packages/taler-util/src/http-client/bank-core.ts index 765348e42..c77f9ddda 100644 --- a/packages/taler-util/src/http-client/core-bank.ts +++ b/packages/taler-util/src/http-client/bank-core.ts @@ -27,6 +27,9 @@ import {  } from "@gnu-taler/taler-util/http";  import { AccessToken, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashoutConversionResponse, codecForCashoutPending, codecForCashouts, codecForCashoutStatusResponse, codecForConversionRatesResponse, codecForCoreBankConfig, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse, codecForTokenSuccessResponse, TalerAuthentication, TalerCorebankApi } from "./types.js";  import { addPaginationParams, makeBasicAuthHeader, makeBearerTokenAuthHeader, PaginationParams, UserAndPassword, UserAndToken } from "./utils.js"; +import { TalerRevenueHttpClient } from "./bank-revenue.js"; +import { TalerWireGatewayHttpClient } from "./bank-wire.js"; +import { TalerBankIntegrationHttpClient } from "./bank-integration.js";  const logger = new Logger("http-client/core-bank.ts"); @@ -465,18 +468,18 @@ export class TalerCoreBankHttpClient {    }    /** - * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api - *  - */ +   * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api +   *  +   */    getWireGatewayAPI(username: string): TalerWireGatewayHttpClient {      const url = new URL(`accounts/${username}/taler-wire-gateway`, this.baseUrl);      return new TalerWireGatewayHttpClient(url.href, username, this.httpLib)    }    /** -* https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api -*  -*/ +  * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api +  *  +  */    getRevenueAPI(username: string): TalerRevenueHttpClient {      const url = new URL(`accounts/${username}/taler-revenue`, this.baseUrl);      return new TalerRevenueHttpClient(url.href, username, this.httpLib,) @@ -484,40 +487,3 @@ export class TalerCoreBankHttpClient {  } -export class TalerBankIntegrationHttpClient { -  httpLib: HttpRequestLibrary; - -  constructor( -    private baseUrl: string, -    httpClient?: HttpRequestLibrary, -  ) { -    this.httpLib = httpClient ?? createPlatformHttpLib(); -  } - -} - -export class TalerWireGatewayHttpClient { -  httpLib: HttpRequestLibrary; - -  constructor( -    private baseUrl: string, -    private username: string, -    httpClient?: HttpRequestLibrary, -  ) { -    this.httpLib = httpClient ?? createPlatformHttpLib(); -  } - -} - -export class TalerRevenueHttpClient { -  httpLib: HttpRequestLibrary; - -  constructor( -    private baseUrl: string, -    private username: string, -    httpClient?: HttpRequestLibrary, -  ) { -    this.httpLib = httpClient ?? createPlatformHttpLib(); -  } - -}
\ No newline at end of file diff --git a/packages/taler-util/src/http-client/bank-integration.ts b/packages/taler-util/src/http-client/bank-integration.ts new file mode 100644 index 000000000..cdba66fa5 --- /dev/null +++ b/packages/taler-util/src/http-client/bank-integration.ts @@ -0,0 +1,44 @@ +import { HttpRequestLibrary, readSuccessResponseJsonOrThrow } from "../http-common.js"; +import { createPlatformHttpLib } from "../http.js"; +import { codecForBankWithdrawalOperationPostResponse } from "../taler-types.js"; +import { TalerBankIntegrationApi, codecForBankVersion, codecForBankWithdrawalOperationStatus } from "./types.js"; + +export class TalerBankIntegrationHttpClient { +  httpLib: HttpRequestLibrary; + +  constructor( +    private baseUrl: string, +    httpClient?: HttpRequestLibrary, +  ) { +    this.httpLib = httpClient ?? createPlatformHttpLib(); +  } + +  /** +   * https://docs.taler.net/core/api-bank-integration.html#get-$BANK_API_BASE_URL-withdrawal-operation-$wopid +   *  +   */ +  async getWithdrawalOperationById(woid: string, timeoutMs?: number): Promise<TalerBankIntegrationApi.BankWithdrawalOperationStatus> { +    const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl); +    if (timeoutMs) { +      url.searchParams.set("long_poll_ms", String(timeoutMs)) +    } +    const resp = await this.httpLib.fetch(url.href, { +      method: "GET" +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForBankWithdrawalOperationStatus()); +  } + +  /** +   * https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid +   *  +   */ +  async completeWithdrawalOperationById(woid: string): Promise<TalerBankIntegrationApi.BankWithdrawalOperationPostResponse> { +    const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl); +    const resp = await this.httpLib.fetch(url.href, { +      method: "POST", +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForBankWithdrawalOperationPostResponse()); +  } + +} + diff --git a/packages/taler-util/src/http-client/bank-revenue.ts b/packages/taler-util/src/http-client/bank-revenue.ts new file mode 100644 index 000000000..99ff71457 --- /dev/null +++ b/packages/taler-util/src/http-client/bank-revenue.ts @@ -0,0 +1,32 @@ +import { HttpRequestLibrary, makeBasicAuthHeader, readSuccessResponseJsonOrThrow } from "../http-common.js"; +import { createPlatformHttpLib } from "../http.js"; +import { TalerRevenueApi, codecForMerchantIncomingHistory } from "./types.js"; +import { UserAndPassword } from "./utils.js"; + +export class TalerRevenueHttpClient { +  httpLib: HttpRequestLibrary; + +  constructor( +    private baseUrl: string, +    private username: string, +    httpClient?: HttpRequestLibrary, +  ) { +    this.httpLib = httpClient ?? createPlatformHttpLib(); +  } + +  /** +   * https://docs.taler.net/core/api-bank-revenue.html#get-$BASE_URL-history +   *  +   * @returns  +   */ +  async getHistory(auth: string): Promise<TalerRevenueApi.MerchantIncomingHistory> { +    const url = new URL(`history`, this.baseUrl); +    const resp = await this.httpLib.fetch(url.href, { +      method: "GET", +      headers: { +        Authorization: makeBasicAuthHeader(this.username, auth), +      } +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForMerchantIncomingHistory()); +  } +}
\ No newline at end of file diff --git a/packages/taler-util/src/http-client/bank-wire.ts b/packages/taler-util/src/http-client/bank-wire.ts new file mode 100644 index 000000000..9f2b859ed --- /dev/null +++ b/packages/taler-util/src/http-client/bank-wire.ts @@ -0,0 +1,98 @@ +import { HttpRequestLibrary, makeBasicAuthHeader, readSuccessResponseJsonOrThrow } from "../http-common.js"; +import { createPlatformHttpLib } from "../http.js"; +import { TalerWireGatewayApi, codecForAddIncomingResponse, codecForIncomingHistory, codecForOutgoingHistory, codecForTransferResponse } from "./types.js"; +import { PaginationParams, UserAndPassword, addPaginationParams } from "./utils.js"; + +/** + * The API is used by the exchange to trigger transactions and query  + * incoming transactions, as well as by the auditor to query incoming  + * and outgoing transactions. + *  + * https://docs.taler.net/core/api-bank-wire.html + */ +export class TalerWireGatewayHttpClient { +  httpLib: HttpRequestLibrary; + +  constructor( +    private baseUrl: string, +    private username: string, +    httpClient?: HttpRequestLibrary, +  ) { +    this.httpLib = httpClient ?? createPlatformHttpLib(); +  } + +  /** +   * https://docs.taler.net/core/api-bank-wire.html#post-$BASE_URL-transfer +   *  +   */ +  async transfer( +    auth: string, +    body: TalerWireGatewayApi.TransferRequest, +  ): Promise<TalerWireGatewayApi.TransferResponse> { +    const url = new URL(`transfer`, this.baseUrl); +    const resp = await this.httpLib.fetch(url.href, { +      method: "POST", +      headers: { +        Authorization: makeBasicAuthHeader(this.username, auth), +      }, +      body +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForTransferResponse()); +  } + +  /** +   * https://docs.taler.net/core/api-bank-wire.html#get-$BASE_URL-history-incoming +   *  +   */ +  async getHistoryIncoming( +    auth: string, +    pagination?: PaginationParams +  ): Promise<TalerWireGatewayApi.IncomingHistory> { +    const url = new URL(`history/incoming`, this.baseUrl); +    addPaginationParams(url, pagination) +    const resp = await this.httpLib.fetch(url.href, { +      method: "GET", +      headers: { +        Authorization: makeBasicAuthHeader(this.username, auth), +      } +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForIncomingHistory()); +  } +  /** +   * https://docs.taler.net/core/api-bank-wire.html#get-$BASE_URL-history-outgoing +   *  +   */ +  async getHistoryOutgoing( +    auth: string, +    pagination?: PaginationParams +  ): Promise<TalerWireGatewayApi.OutgoingHistory> { +    const url = new URL(`history/outgoing`, this.baseUrl); +    addPaginationParams(url, pagination) +    const resp = await this.httpLib.fetch(url.href, { +      method: "GET", +      headers: { +        Authorization: makeBasicAuthHeader(this.username, auth), +      } +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForOutgoingHistory()); +  } +  /** +   * https://docs.taler.net/core/api-bank-wire.html#post-$BASE_URL-admin-add-incoming +   *  +   */ +  async addIncoming( +    auth: string, +    body: TalerWireGatewayApi.AddIncomingRequest, +  ): Promise<TalerWireGatewayApi.AddIncomingResponse> { +    const url = new URL(`admin/add-incoming`, this.baseUrl); +    const resp = await this.httpLib.fetch(url.href, { +      method: "POST", +      headers: { +        Authorization: makeBasicAuthHeader(this.username, auth), +      }, +      body +    }); +    return readSuccessResponseJsonOrThrow(resp, codecForAddIncomingResponse()); +  } +} + diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts index 047f2fe8e..5f899dd5a 100644 --- a/packages/taler-util/src/http-client/types.ts +++ b/packages/taler-util/src/http-client/types.ts @@ -1,42 +1,120 @@ -import { codecForAmountJson, codecForAmountString } from "../amounts.js"; -import { TalerCorebankApiClient } from "../bank-api-client.js"; -import { Codec, buildCodecForObject, codecForAny, codecForBoolean, codecForConstString, codecForEither, codecForList, codecForMap, codecForNumber, codecForString, codecOptional } from "../codec.js"; +import { codecForAmountString } from "../amounts.js"; +import { Codec, buildCodecForObject, buildCodecForUnion, codecForBoolean, codecForConstString, codecForEither, codecForList, codecForMap, codecForNumber, codecForString, codecOptional } from "../codec.js";  import { codecForTimestamp } from "../time.js"; +/// +/// HASH +/// + +// 64-byte hash code.  type HashCode = string; + +// 32-byte hash code. +type ShortHashCode = string; + +// 16-byte salt. +type WireSalt = string; + +type SHA256HashCode = ShortHashCode; + +type SHA512HashCode = HashCode; + +// 32-byte nonce value, must only be used once. +type CSNonce = string; + +// 32-byte nonce value, must only be used once. +type RefreshMasterSeed = string; + +// 32-byte value representing a point on Curve25519. +type Cs25519Point = string; + +// 32-byte value representing a scalar multiplier +// for scalar operations on points on Curve25519. +type Cs25519Scalar = string; + +/// +/// KEYS +/// + +// 16-byte access token used to authorize access. +type ClaimToken = string; + +// EdDSA and ECDHE public keys always point on Curve25519 +// and represented  using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32.  type EddsaPublicKey = string; -type EddsaSignature = string; + +// EdDSA and ECDHE public keys always point on Curve25519 +// and represented  using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32. +type EddsaPrivateKey = string; + +// Edx25519 public keys are points on Curve25519 and represented using the +// standard 256 bits Ed25519 compact format converted to Crockford +// Base32. +type Edx25519PublicKey = string; + +// Edx25519 private keys are always points on Curve25519 +// and represented using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32. +type Edx25519PrivateKey = string; + +// EdDSA and ECDHE public keys always point on Curve25519 +// and represented  using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32. +type EcdhePublicKey = string; + +// Point on Curve25519 represented using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32. +type CsRPublic = string; + +// EdDSA and ECDHE public keys always point on Curve25519 +// and represented  using the standard 256 bits Ed25519 compact format, +// converted to Crockford Base32. +type EcdhePrivateKey = string; + +type CoinPublicKey = EddsaPublicKey; + +// RSA public key converted to Crockford Base32. +type RsaPublicKey = string; + +type Integer = number; +  type WireTransferIdentifierRawP = string; -type RelativeTime = { -  d_us: number | "forever" -}; +// Subset of numbers:  Integers in the +// inclusive range 0 .. (2^53 - 1). +type SafeUint64 = number; + +// The string must be a data URL according to RFC 2397 +// with explicit mediatype and base64 parameters. +// +//     data:<mediatype>;base64,<data> +// +// Supported mediatypes are image/jpeg and image/png. +// Invalid strings will be rejected by the wallet.  type ImageDataUrl = string; -interface WithId { -  id: string; -} + +// <Currency>:<DecimalAmount>.  +type Amount = string; + +type WadId = string;  interface Timestamp { -  // Milliseconds since epoch, or the special -  // value "forever" to represent an event that will +  // Seconds since epoch, or the special +  // value "never" to represent an event that will    // never happen.    t_s: number | "never";  } -interface Duration { -  d_us: number | "forever"; -} -interface WithId { -  id: string; +interface RelativeTime { +  // Duration in microseconds or "forever" +  // to represent an infinite duration. Numeric +  // values are capped at 2^53 - 1 inclusive. +  d_us: number | "forever";  } -type UUID = string; -type Integer = number; - -type Amount = string; - -  export interface LoginToken {    token: AccessToken,    expiration: Timestamp, @@ -78,7 +156,7 @@ export namespace TalerAuthentication {    }  } -interface CurrencySpecification { +export interface CurrencySpecification {    // Name of the currency.    name: string; @@ -262,53 +340,173 @@ export const codecForGlobalCashouts =  export const codecForGlobalCashoutInfo =    (): Codec<TalerCorebankApi.GlobalCashoutInfo> =>      buildCodecForObject<TalerCorebankApi.GlobalCashoutInfo>() -    .property("cashout_id", codecForString()) -    .property("username", codecForString()) -    .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"),)) +      .property("cashout_id", codecForString()) +      .property("username", codecForString()) +      .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"),))        .build("TalerCorebankApi.GlobalCashoutInfo");  export const codecForCashoutStatusResponse =    (): Codec<TalerCorebankApi.CashoutStatusResponse> =>      buildCodecForObject<TalerCorebankApi.CashoutStatusResponse>() -    .property("amount_credit", codecForAmountString()) -    .property("amount_debit", codecForAmountString()) -    .property("confirmation_time", codecForTimestamp) -    .property("creation_time", codecForTimestamp) -    .property("credit_payto_uri", codecForPaytoURI()) -    .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"))) -    .property("subject", codecForString()) -    .build("TalerCorebankApi.CashoutStatusResponse"); +      .property("amount_credit", codecForAmountString()) +      .property("amount_debit", codecForAmountString()) +      .property("confirmation_time", codecForTimestamp) +      .property("creation_time", codecForTimestamp) +      .property("credit_payto_uri", codecForPaytoURI()) +      .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"))) +      .property("subject", codecForString()) +      .build("TalerCorebankApi.CashoutStatusResponse");  export const codecForConversionRatesResponse =    (): Codec<TalerCorebankApi.ConversionRatesResponse> =>      buildCodecForObject<TalerCorebankApi.ConversionRatesResponse>() -    .property("buy_at_ratio", codecForDecimalNumber()) -    .property("buy_in_fee", codecForDecimalNumber()) -    .property("sell_at_ratio", codecForDecimalNumber()) -    .property("sell_out_fee", codecForDecimalNumber()) -    .build("TalerCorebankApi.ConversionRatesResponse"); +      .property("buy_at_ratio", codecForDecimalNumber()) +      .property("buy_in_fee", codecForDecimalNumber()) +      .property("sell_at_ratio", codecForDecimalNumber()) +      .property("sell_out_fee", codecForDecimalNumber()) +      .build("TalerCorebankApi.ConversionRatesResponse");  export const codecForMonitorResponse =    (): Codec<TalerCorebankApi.MonitorResponse> =>      buildCodecForObject<TalerCorebankApi.MonitorResponse>() -    .property("cashinCount", codecForNumber()) -    .property("cashinExternalVolume", codecForAmountString()) -    .property("cashoutCount", codecForNumber()) -    .property("cashoutExternalVolume", codecForAmountString()) -    .property("talerPayoutCount", codecForNumber()) -    .property("talerPayoutInternalVolume", codecForAmountString()) -    .build("TalerCorebankApi.MonitorResponse"); +      .property("cashinCount", codecForNumber()) +      .property("cashinExternalVolume", codecForAmountString()) +      .property("cashoutCount", codecForNumber()) +      .property("cashoutExternalVolume", codecForAmountString()) +      .property("talerPayoutCount", codecForNumber()) +      .property("talerPayoutInternalVolume", codecForAmountString()) +      .build("TalerCorebankApi.MonitorResponse"); + +export const codecForBankVersion = +  (): Codec<TalerBankIntegrationApi.BankVersion> => +    buildCodecForObject<TalerBankIntegrationApi.BankVersion>() +      .property("currency", codecForCurrencyName()) +      .property("currency_specification", codecForCurrencySpecificiation()) +      .property("name", codecForConstString("taler-bank-integration")) +      .property("version", codecForLibtoolVersion()) +      .build("TalerBankIntegrationApi.BankVersion"); + +export const codecForBankWithdrawalOperationStatus = +  (): Codec<TalerBankIntegrationApi.BankWithdrawalOperationStatus> => +    buildCodecForObject<TalerBankIntegrationApi.BankWithdrawalOperationStatus>() +      .property("aborted", codecForBoolean()) +      .property("amount", codecForAmountString()) +      .property("confirm_transfer_url", codecOptional(codecForURL())) +      .property("selection_done", codecForBoolean()) +      .property("sender_wire", codecForPaytoURI()) +      .property("suggested_exchange", codecOptional(codecForString())) +      .property("transfer_done", codecForBoolean()) +      .property("wire_types", codecForList(codecForString())) +      .build("TalerBankIntegrationApi.BankWithdrawalOperationStatus"); + +export const codecForBankWithdrawalOperationPostResponse = +  (): Codec<TalerBankIntegrationApi.BankWithdrawalOperationPostResponse> => +    buildCodecForObject<TalerBankIntegrationApi.BankWithdrawalOperationPostResponse>() +      .property("confirm_transfer_url", codecForURL()) +      .property("transfer_done", codecForBoolean()) +      .build("TalerBankIntegrationApi.BankWithdrawalOperationPostResponse"); + +export const codecForMerchantIncomingHistory = +  (): Codec<TalerRevenueApi.MerchantIncomingHistory> => +    buildCodecForObject<TalerRevenueApi.MerchantIncomingHistory>() +      .property("credit_account", codecForPaytoURI()) +      .property("incoming_transactions", codecForList(codecForMerchantIncomingBankTransaction())) +      .build("TalerRevenueApi.MerchantIncomingHistory"); + +export const codecForMerchantIncomingBankTransaction = +  (): Codec<TalerRevenueApi.MerchantIncomingBankTransaction> => +    buildCodecForObject<TalerRevenueApi.MerchantIncomingBankTransaction>() +      .property("amount", codecForAmountString()) +      .property("date", codecForTimestamp) +      .property("debit_account", codecForPaytoURI()) +      .property("exchange_url", codecForURL()) +      .property("row_id", codecForNumber()) +      .property("wtid", codecForString()) +      .build("TalerRevenueApi.MerchantIncomingBankTransaction"); + +export const codecForTransferResponse = +  (): Codec<TalerWireGatewayApi.TransferResponse> => +    buildCodecForObject<TalerWireGatewayApi.TransferResponse>() +      .property("row_id", codecForNumber()) +      .property("timestamp", codecForTimestamp) +      .build("TalerWireGatewayApi.TransferResponse"); + +export const codecForIncomingHistory = +  (): Codec<TalerWireGatewayApi.IncomingHistory> => +    buildCodecForObject<TalerWireGatewayApi.IncomingHistory>() +      .property("credit_account", codecForString()) +      .property("incoming_transactions", codecForList(codecForIncomingBankTransaction())) +      .build("TalerWireGatewayApi.IncomingHistory"); + +export const codecForIncomingBankTransaction = (): Codec<TalerWireGatewayApi.IncomingBankTransaction> => buildCodecForUnion<TalerWireGatewayApi.IncomingBankTransaction>() +  .discriminateOn("type") +  .alternative("RESERVE", codecForIncomingReserveTransaction()) +  .alternative("WAD", codecForIncomingWadTransaction()) +  .build("TalerWireGatewayApi.IncomingBankTransaction"); + +export const codecForIncomingReserveTransaction = +  (): Codec<TalerWireGatewayApi.IncomingReserveTransaction> => +    buildCodecForObject<TalerWireGatewayApi.IncomingReserveTransaction>() +      .property("amount", codecForAmountString()) +      .property("date", codecForTimestamp) +      .property("debit_account", codecForPaytoURI()) +      .property("reserve_pub", codecForString()) +      .property("row_id", codecForNumber()) +      .property("type", codecForConstString("RESERVE")) +      .build("TalerWireGatewayApi.IncomingReserveTransaction"); + +export const codecForIncomingWadTransaction = +  (): Codec<TalerWireGatewayApi.IncomingWadTransaction> => +    buildCodecForObject<TalerWireGatewayApi.IncomingWadTransaction>() +      .property("amount", codecForAmountString()) +      .property("credit_account", codecForPaytoURI()) +      .property("date", codecForTimestamp) +      .property("debit_account", codecForPaytoURI()) +      .property("origin_exchange_url", codecForURL()) +      .property("row_id", codecForNumber()) +      .property("type", codecForConstString("WAD")) +      .property("wad_id", codecForString()) +      .build("TalerWireGatewayApi.IncomingWadTransaction"); + +export const codecForOutgoingHistory = +  (): Codec<TalerWireGatewayApi.OutgoingHistory> => +    buildCodecForObject<TalerWireGatewayApi.OutgoingHistory>() +      .property("debit_account", codecForString()) +      .property("outgoing_transactions", codecForList(codecForOutgoingBankTransaction())) +      .build("TalerWireGatewayApi.OutgoingHistory"); + +export const codecForOutgoingBankTransaction = +  (): Codec<TalerWireGatewayApi.OutgoingBankTransaction> => +    buildCodecForObject<TalerWireGatewayApi.OutgoingBankTransaction>() +      .property("amount", codecForAmountString()) +      .property("credit_account", codecForPaytoURI()) +      .property("date", codecForTimestamp) +      .property("exchange_base_url", codecForURL()) +      .property("row_id", codecForNumber()) +      .property("wtid", codecForString()) +      .build("TalerWireGatewayApi.OutgoingBankTransaction"); + +export const codecForAddIncomingResponse = +  (): Codec<TalerWireGatewayApi.AddIncomingResponse> => +    buildCodecForObject<TalerWireGatewayApi.AddIncomingResponse>() +      .property("row_id", codecForNumber()) +      .property("timestamp", codecForTimestamp) +      .build("TalerWireGatewayApi.AddIncomingResponse");  // export const codecFor = -//   (): Codec<TalerCorebankApi.PublicAccountsResponse> => -//     buildCodecForObject<TalerCorebankApi.PublicAccountsResponse>() +//   (): Codec<TalerWireGatewayApi.PublicAccountsResponse> => +//     buildCodecForObject<TalerWireGatewayApi.PublicAccountsResponse>()  //       .property("", codecForString()) -//       .build("TalerCorebankApi.PublicAccountsResponse"); +//       .build("TalerWireGatewayApi.PublicAccountsResponse"); +  type EmailAddress = string;  type PhoneNumber = string;  type DecimalNumber = string; +const codecForURL = codecForString +const codecForLibtoolVersion = codecForString +const codecForCurrencyName = codecForString  const codecForPaytoURI = codecForString  const codecForTalerWithdrawalURI = codecForString  const codecForDecimalNumber = codecForString @@ -319,7 +517,289 @@ enum TanChannel {    FILE = "file"  } +export namespace TalerWireGatewayApi { + +  export interface TransferResponse { + +    // Timestamp that indicates when the wire transfer will be executed. +    // In cases where the wire transfer gateway is unable to know when +    // the wire transfer will be executed, the time at which the request +    // has been received and stored will be returned. +    // The purpose of this field is for debugging (humans trying to find +    // the transaction) as well as for taxation (determining which +    // time period a transaction belongs to). +    timestamp: Timestamp; + +    // Opaque ID of the transaction that the bank has made. +    row_id: SafeUint64; +  } + +  export interface TransferRequest { +    // Nonce to make the request idempotent.  Requests with the same +    // transaction_uid that differ in any of the other fields +    // are rejected. +    request_uid: HashCode; + +    // Amount to transfer. +    amount: Amount; + +    // Base URL of the exchange.  Shall be included by the bank gateway +    // in the appropriate section of the wire transfer details. +    exchange_base_url: string; + +    // Wire transfer identifier chosen by the exchange, +    // used by the merchant to identify the Taler order(s) +    // associated with this wire transfer. +    wtid: ShortHashCode; + +    // The recipient's account identifier as a payto URI. +    credit_account: string; +  } + +  export interface IncomingHistory { + +    // Array of incoming transactions. +    incoming_transactions: IncomingBankTransaction[]; + +    // Payto URI to identify the receiver of funds. +    // This must be one of the exchange's bank accounts. +    // Credit account is shared by all incoming transactions +    // as per the nature of the request. +    credit_account: string; + +  } + +  // Union discriminated by the "type" field. +  export type IncomingBankTransaction = +    | IncomingReserveTransaction +    | IncomingWadTransaction; + +  export interface IncomingReserveTransaction { +    type: "RESERVE"; + +    // Opaque identifier of the returned record. +    row_id: SafeUint64; + +    // Date of the transaction. +    date: Timestamp; + +    // Amount transferred. +    amount: Amount; + +    // Payto URI to identify the sender of funds. +    debit_account: string; + +    // The reserve public key extracted from the transaction details. +    reserve_pub: EddsaPublicKey; + +  } + +  export interface IncomingWadTransaction { +    type: "WAD"; + +    // Opaque identifier of the returned record. +    row_id: SafeUint64; + +    // Date of the transaction. +    date: Timestamp; + +    // Amount transferred. +    amount: Amount; + +    // Payto URI to identify the receiver of funds. +    // This must be one of the exchange's bank accounts. +    credit_account: string; + +    // Payto URI to identify the sender of funds. +    debit_account: string; + +    // Base URL of the exchange that originated the wad. +    origin_exchange_url: string; + +    // The reserve public key extracted from the transaction details. +    wad_id: WadId; +  } + + +  export interface OutgoingHistory { + +    // Array of outgoing transactions. +    outgoing_transactions: OutgoingBankTransaction[]; + +    // Payto URI to identify the sender of funds. +    // This must be one of the exchange's bank accounts. +    // Credit account is shared by all incoming transactions +    // as per the nature of the request. +    debit_account: string; + +  } + +  export interface OutgoingBankTransaction { + +    // Opaque identifier of the returned record. +    row_id: SafeUint64; + +    // Date of the transaction. +    date: Timestamp; + +    // Amount transferred. +    amount: Amount; + +    // Payto URI to identify the receiver of funds. +    credit_account: string; + +    // The wire transfer ID in the outgoing transaction. +    wtid: ShortHashCode; + +    // Base URL of the exchange. +    exchange_base_url: string; +  } + +  export interface AddIncomingRequest { +    // Amount to transfer. +    amount: Amount; + +    // Reserve public key that is included in the wire transfer details +    // to identify the reserve that is being topped up. +    reserve_pub: EddsaPublicKey; + +    // Account (as payto URI) that makes the wire transfer to the exchange. +    // Usually this account must be created by the test harness before this API is +    // used.  An exception is the "exchange-fakebank", where any debit account can be +    // specified, as it is automatically created. +    debit_account: string; +  } + +  export interface AddIncomingResponse { + +    // Timestamp that indicates when the wire transfer will be executed. +    // In cases where the wire transfer gateway is unable to know when +    // the wire transfer will be executed, the time at which the request +    // has been received and stored will be returned. +    // The purpose of this field is for debugging (humans trying to find +    // the transaction) as well as for taxation (determining which +    // time period a transaction belongs to). +    timestamp: Timestamp; + +    // Opaque ID of the transaction that the bank has made. +    row_id: SafeUint64; +  } + + + +} + +export namespace TalerRevenueApi { +  export interface MerchantIncomingHistory { + +    // Array of incoming transactions. +    incoming_transactions: MerchantIncomingBankTransaction[]; + +    // Payto URI to identify the receiver of funds. +    // This must be one of the merchant's bank accounts. +    // Credit account is shared by all incoming transactions +    // as per the nature of the request. +    credit_account: string; + +  } +  export interface MerchantIncomingBankTransaction { + +    // Opaque identifier of the returned record. +    row_id: SafeUint64; + +    // Date of the transaction. +    date: Timestamp; + +    // Amount transferred. +    amount: Amount; + +    // Payto URI to identify the sender of funds. +    debit_account: string; + +    // Base URL of the exchange where the transfer originated form. +    exchange_url: string; + +    // The wire transfer identifier. +    wtid: WireTransferIdentifierRawP; +  } +} + +export namespace TalerBankIntegrationApi { +  export interface BankVersion { +    // 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 bank. +    currency: string; + +    // How the bank SPA should render this currency. +    currency_specification: CurrencySpecification; + +    // Name of the API. +    name: "taler-bank-integration"; +  } + +  export interface BankWithdrawalOperationStatus { +    // Indicates whether the withdrawal was aborted. +    aborted: boolean; + +    // Has the wallet selected parameters for the withdrawal operation +    // (exchange and reserve public key) and successfully sent it +    // to the bank? +    selection_done: boolean; + +    // The transfer has been confirmed and registered by the bank. +    // Does not guarantee that the funds have arrived at the exchange already. +    transfer_done: boolean; + +    // Amount that will be withdrawn with this operation +    // (raw amount without fee considerations). +    amount: Amount; + +    // Bank account of the customer that is withdrawing, as a +    // payto URI. +    sender_wire?: string; + +    // Suggestion for an exchange given by the bank. +    suggested_exchange?: string; + +    // URL that the user needs to navigate to in order to +    // complete some final confirmation (e.g. 2FA). +    // It may contain withdrawal operation id +    confirm_transfer_url?: string; + +    // Wire transfer types supported by the bank. +    wire_types: string[]; +  } + +  export interface BankWithdrawalOperationPostRequest { + +    // Reserve public key. +    reserve_pub: string; + +    // Payto address of the exchange selected for the withdrawal. +    selected_exchange: string; +  } + +  export interface BankWithdrawalOperationPostResponse { + +    // The transfer has been confirmed and registered by the bank. +    // Does not guarantee that the funds have arrived at the exchange already. +    transfer_done: boolean; + +    // URL that the user needs to navigate to in order to +    // complete some final confirmation (e.g. 2FA). +    // +    // Only applicable when transfer_done is false. +    // It may contain withdrawal operation id +    confirm_transfer_url?: string; +  } + + +}  export namespace TalerCorebankApi {    export interface Config { @@ -648,21 +1128,21 @@ export namespace TalerCorebankApi {      // Exchange rate to buy the local currency from the external one      buy_at_ratio: DecimalNumber; -   +      // Exchange rate to sell the local currency for the external one      sell_at_ratio: DecimalNumber; -   +      // Fee to subtract after applying the buy ratio.      buy_in_fee: DecimalNumber; -   +      // Fee to subtract after applying the sell ratio.      sell_out_fee: DecimalNumber;    } -   -  export enum MonitorTimeframeParam{ + +  export enum MonitorTimeframeParam {      hour, day, month, year, decade,    } -   +    export interface MonitorResponse {      // This number identifies how many cashin operations diff --git a/packages/taler-util/src/http-client/utils.ts b/packages/taler-util/src/http-client/utils.ts index ecb4d14c4..4588f945c 100644 --- a/packages/taler-util/src/http-client/utils.ts +++ b/packages/taler-util/src/http-client/utils.ts @@ -31,9 +31,10 @@ export function addPaginationParams(url: URL, pagination?: PaginationParams) {    if (pagination.offset) {      url.searchParams.set("start", pagination.offset)    } -  if (pagination.limit) { -    url.searchParams.set("delta", String(pagination.limit)) -  } +  const order = !pagination || pagination.order === "asc" ? 1 : -1 +  const limit = !pagination || !pagination.limit || pagination.limit === 0 ? 5 : Math.abs(pagination.limit) +  //always send delta +  url.searchParams.set("delta", String(order * limit))  }  export type UserAndPassword = { @@ -53,10 +54,15 @@ export type PaginationParams = {    offset?: string,    /**     * max number of element in the result response +   * always greater than 0     */    limit?: number,    /**     * milliseconds the server should wait for at least one result to be shown     */    timoutMs?: number, +  /** +   * order +   */ +  order: "asc" | "dec"  }  | 
