aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-11-13 15:33:13 -0300
committerSebastian <sebasjm@gmail.com>2023-11-13 15:33:29 -0300
commitca076e5eab10d2d471dd68732a7d8a7ac9f5f6bc (patch)
treed12a9233ec2274e2fe66005db6ee9fbb4123a632 /packages
parent23e567b6a78bb9590e4c6f3aa193dc2192c705cf (diff)
downloadwallet-core-ca076e5eab10d2d471dd68732a7d8a7ac9f5f6bc.tar.xz
fix new libeufin api
Diffstat (limited to 'packages')
-rw-r--r--packages/demobank-ui/src/hooks/circuit.ts30
-rw-r--r--packages/demobank-ui/src/pages/ShowAccountDetails.tsx2
-rw-r--r--packages/demobank-ui/src/pages/admin/AdminHome.tsx14
-rw-r--r--packages/demobank-ui/src/pages/business/CreateCashout.tsx52
-rw-r--r--packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx30
-rw-r--r--packages/demobank-ui/src/utils.ts1
-rw-r--r--packages/taler-harness/src/http-client/bank-core.ts21
-rw-r--r--packages/taler-util/src/http-client/bank-core.ts89
-rw-r--r--packages/taler-util/src/http-client/types.ts185
9 files changed, 275 insertions, 149 deletions
diff --git a/packages/demobank-ui/src/hooks/circuit.ts b/packages/demobank-ui/src/hooks/circuit.ts
index 845f37822..44edb4f8a 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -266,26 +266,34 @@ export function useLastMonitorInfo(time: Date, timeframe: TalerCorebankApi.Monit
const current: TalerCoreBankResultByMethod<"getMonitor"> = {
type: "ok" as const,
body: {
- type: "with-cashout" as const,
+ type: "with-conversions" as const,
cashinCount: 1,
- cashinExternalVolume: "LOCAL:1234" as AmountString,
+ cashinFiatVolume: "LOCAL:2345" as AmountString,
+ cashinRegionalVolume: "LOCAL:2345" as AmountString,
cashoutCount: 2,
- cashoutExternalVolume: "LOCAL:2345" as AmountString,
- talerPayoutCount: 3,
- talerPayoutInternalVolume: "LOCAL:3456" as AmountString,
+ cashoutFiatVolume: "LOCAL:2345" as AmountString,
+ cashoutRegionalVolume: "LOCAL:2345" as AmountString,
+ talerInCount: 1,
+ talerInVolume: "LOCAL:2345" as AmountString,
+ talerOutCount: 2,
+ talerOutVolume: "LOCAL:2345" as AmountString,
}
}
- const previous = {
+ const previous: TalerCoreBankResultByMethod<"getMonitor"> = {
type: "ok" as const,
body: {
- type: "with-cashout" as const,
+ type: "with-conversions" as const,
cashinCount: 1,
- cashinExternalVolume: "LOCAL:2345" as AmountString,
+ cashinFiatVolume: "LOCAL:2345" as AmountString,
+ cashinRegionalVolume: "LOCAL:2345" as AmountString,
cashoutCount: 2,
- cashoutExternalVolume: "LOCAL:2345" as AmountString,
- talerPayoutCount: 3,
- talerPayoutInternalVolume: "LOCAL:3456" as AmountString,
+ cashoutFiatVolume: "LOCAL:2345" as AmountString,
+ cashoutRegionalVolume: "LOCAL:2345" as AmountString,
+ talerInCount: 1,
+ talerInVolume: "LOCAL:2345" as AmountString,
+ talerOutCount: 2,
+ talerOutVolume: "LOCAL:2345" as AmountString,
}
}
diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
index 2e00fdbba..a88a90499 100644
--- a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
@@ -58,7 +58,7 @@ export function ShowAccountDetails({
email: submitAccount.contact_data?.email,
phone: submitAccount.contact_data?.phone,
}),
- is_exchange: false,
+ is_taler_exchange: false,
name: submitAccount.name,
});
diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
index 9bc2ee571..a89b4afca 100644
--- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
@@ -124,15 +124,15 @@ function Metrics(): VNode {
</div>
<dl class="mt-5 grid grid-cols-1 divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow-lg md:grid-cols-3 md:divide-x md:divide-y-0">
- {resp.current.body.type !== "with-cashout" || resp.previous.body.type !== "with-cashout" ? undefined :
+ {resp.current.body.type !== "with-conversions" || resp.previous.body.type !== "with-conversions" ? undefined :
<Fragment>
<div class="px-4 py-5 sm:p-6">
<dt class="text-base font-normal text-gray-900">
<i18n.Translate>Cashin</i18n.Translate>
</dt>
<MetricValue
- current={resp.current.body.cashinExternalVolume}
- previous={resp.previous.body.cashinExternalVolume}
+ current={resp.current.body.cashinFiatVolume}
+ previous={resp.previous.body.cashinFiatVolume}
/>
</div>
<div class="px-4 py-5 sm:p-6">
@@ -140,8 +140,8 @@ function Metrics(): VNode {
<i18n.Translate>Cashout</i18n.Translate>
</dt>
<MetricValue
- current={resp.current.body.cashoutExternalVolume}
- previous={resp.previous.body.cashoutExternalVolume}
+ current={resp.current.body.cashoutFiatVolume}
+ previous={resp.previous.body.cashoutFiatVolume}
/>
</div>
</Fragment>
@@ -151,8 +151,8 @@ function Metrics(): VNode {
<i18n.Translate>Payout</i18n.Translate>
</dt>
<MetricValue
- current={resp.current.body.talerPayoutInternalVolume}
- previous={resp.previous.body.talerPayoutInternalVolume}
+ current={resp.current.body.talerOutVolume}
+ previous={resp.previous.body.talerOutVolume}
/>
</div>
</dl>
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 10be5ec11..525a170bc 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -16,19 +16,22 @@
import {
Amounts,
TalerError,
- TranslatedString
+ TranslatedString,
+ encodeCrock,
+ getRandomBytes
} from "@gnu-taler/taler-util";
import {
+ Attention,
+ ErrorLoading,
+ Loading,
+ LocalNotificationBanner,
+ ShowInputErrorLabel,
useLocalNotification,
useTranslationContext
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { mutate } from "swr";
-import { Attention } from "@gnu-taler/web-util/browser";
-import { ErrorLoading } from "@gnu-taler/web-util/browser";
-import { Loading } from "@gnu-taler/web-util/browser";
-import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useAccountDetails } from "../../hooks/access.js";
import { useBackendState } from "../../hooks/backend.js";
@@ -37,13 +40,11 @@ import {
} from "../../hooks/circuit.js";
import {
TanChannel,
- undefinedIfEmpty,
- withRuntimeErrorHandling
+ undefinedIfEmpty
} from "../../utils.js";
import { LoginForm } from "../LoginForm.js";
import { InputAmount } from "../PaytoWireTransferForm.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { LocalNotificationBanner } from "@gnu-taler/web-util/browser";
interface Props {
account: string;
@@ -321,21 +322,6 @@ export function CreateCashout({
updateForm(structuredClone(form));
}}
/>
- <input
- class={
- "pure-button content " +
- (form.channel === TanChannel.FILE
- ? "pure-button-primary"
- : "pure-button-secondary")
- }
- type="submit"
- value={i18n.str`FILE`}
- onClick={async (e) => {
- e.preventDefault();
- form.channel = TanChannel.FILE;
- updateForm(structuredClone(form));
- }}
- />
</div>
<ShowInputErrorLabel
message={errors?.channel}
@@ -363,7 +349,9 @@ export function CreateCashout({
if (errors || !creds) return;
await handleError(async () => {
+ const request_uid = encodeCrock(getRandomBytes(16))
const resp = await api.createCashout(creds, {
+ request_uid,
amount_credit: Amounts.stringify(calc.credit),
amount_debit: Amounts.stringify(calc.debit),
subject: form.subject,
@@ -404,12 +392,18 @@ export function CreateCashout({
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
});
- // case "": return notify({
- // type: "error",
- // title: i18n.str`This user is not allowed to make a cashout`,
- // description: resp.detail.hint as TranslatedString,
- // debug: resp.detail,
- // });
+ case "request-already-used": return notify({
+ type: "error",
+ title: i18n.str`Duplicated request found, try again.`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
+ case "tan-failed": return notify({
+ type: "error",
+ title: i18n.str`Server couldn't send the confirmation request.`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
default: assertUnreachable(resp)
}
}
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
index 4646e9220..ddfc18a0c 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
@@ -121,12 +121,12 @@ export function ShowCashoutDetails({
</label>
<input readOnly value={result.body.status} />
</fieldset>
- <fieldset>
+ {/* <fieldset>
<label>
<i18n.Translate>Destination</i18n.Translate>
</label>
<input readOnly value={result.body.credit_payto_uri} />
- </fieldset>
+ </fieldset> */}
{isPending ? (
<fieldset>
<label>
@@ -220,15 +220,33 @@ export function ShowCashoutDetails({
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "wrong-tan-or-credential": return notify({
+ case "no-enough-balance": return notify({
+ type: "error",
+ title: i18n.str`The account does not have sufficient funds`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
+ case "incorrect-exchange-rate": return notify({
+ type: "error",
+ title: i18n.str`The exchange rate was incorrectly applied`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
+ case "already-aborted": return notify({
+ type: "error",
+ title: i18n.str`The cashout operation is already aborted.`,
+ description: resp.detail.hint as TranslatedString,
+ debug: resp.detail,
+ });
+ case "no-cashout-payto": return notify({
type: "error",
- title: i18n.str`Invalid code or credentials.`,
+ title: i18n.str`Missing destination account.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
- case "cashout-address-changed": return notify({
+ case "too-many-attempts": return notify({
type: "error",
- title: i18n.str`The cash-out address between the creation and the confirmation changed.`,
+ title: i18n.str`Too many failed attempts.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
})
diff --git a/packages/demobank-ui/src/utils.ts b/packages/demobank-ui/src/utils.ts
index 437618150..18abf28a9 100644
--- a/packages/demobank-ui/src/utils.ts
+++ b/packages/demobank-ui/src/utils.ts
@@ -78,7 +78,6 @@ export type RecursivePartial<T> = {
export enum TanChannel {
SMS = "sms",
EMAIL = "email",
- FILE = "file",
}
export enum CashoutStatus {
// The payment was initiated after a valid
diff --git a/packages/taler-harness/src/http-client/bank-core.ts b/packages/taler-harness/src/http-client/bank-core.ts
index 9919fc0a7..22a10580d 100644
--- a/packages/taler-harness/src/http-client/bank-core.ts
+++ b/packages/taler-harness/src/http-client/bank-core.ts
@@ -16,13 +16,18 @@ export function createTestForBankCore(api: TalerCoreBankHttpClient, adminToken:
"no-contact-info": undefined,
"no-enough-balance": undefined,
"cashout-not-supported": undefined,
+ "request-already-used": undefined,
+ "tan-failed": undefined,
success: undefined,
},
test_confirmCashoutById: {
- "cashout-address-changed": undefined,
+ "already-aborted": undefined,
+ "incorrect-exchange-rate": undefined,
+ "no-cashout-payto": undefined,
+ "no-enough-balance": undefined,
+ "too-many-attempts": undefined,
"cashout-not-supported": undefined,
"not-found": undefined,
- "wrong-tan-or-credential": undefined,
success: undefined,
},
test_getAccountCashouts: {
@@ -37,8 +42,18 @@ export function createTestForBankCore(api: TalerCoreBankHttpClient, adminToken:
},
test_getCashoutRate: {
"cashout-not-supported": undefined,
- "not-supported": undefined,
"wrong-calculation": undefined,
+ "amount-too-small": undefined,
+ "missing-params": undefined,
+ "wrong-currency": undefined,
+ success: undefined,
+ },
+ test_getCashinRate: {
+ "cashout-not-supported": undefined,
+ "wrong-calculation": undefined,
+ "amount-too-small": undefined,
+ "missing-params": undefined,
+ "wrong-currency": undefined,
success: undefined,
},
test_getGlobalCashouts: {
diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts
index 1107a3c93..0b99943a3 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -31,7 +31,7 @@ import { TalerAuthenticationHttpClient } from "./authentication.js";
import { TalerBankIntegrationHttpClient } from "./bank-integration.js";
import { TalerRevenueHttpClient } from "./bank-revenue.js";
import { TalerWireGatewayHttpClient } from "./bank-wire.js";
-import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashoutConversionResponse, codecForCashoutPending, codecForCashoutStatusResponse, codecForCashouts, codecForCoreBankConfig, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse } from "./types.js";
+import { AccessToken, PaginationParams, TalerCorebankApi, UserAndToken, codecForAccountData, codecForBankAccountCreateWithdrawalResponse, codecForBankAccountGetWithdrawalResponse, codecForBankAccountTransactionInfo, codecForBankAccountTransactionsResponse, codecForCashinConversionResponse, codecForCashoutConversionResponse, codecForCashoutPending, codecForCashoutStatusResponse, codecForCashouts, codecForCoreBankConfig, codecForGlobalCashouts, codecForListBankAccountsResponse, codecForMonitorResponse, codecForPublicAccountsResponse } from "./types.js";
import { addPaginationParams, makeBearerTokenAuthHeader } from "./utils.js";
@@ -181,6 +181,9 @@ export class TalerCoreBankHttpClient {
case HttpStatusCode.NoContent: return opEmptySuccess()
case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", resp);
+ //FIXME: add code to split cases
+ // * An admin account tried to make its account an exchange
+ // * A non-admin user tried to change properties reserved for the admin
case HttpStatusCode.Forbidden: return opKnownFailure("old-password-invalid-or-not-allowed", resp);
default: return opUnknownFailure(resp, await resp.text())
}
@@ -444,13 +447,15 @@ export class TalerCoreBankHttpClient {
const body = await resp.json()
const details = codecForTalerErrorDetail().decode(body)
switch (details.code) {
+ case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return opKnownFailure("request-already-used", resp);
case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownFailure("incorrect-exchange-rate", resp);
case TalerErrorCode.BANK_MISSING_TAN_INFO: return opKnownFailure("no-contact-info", resp);
case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("no-enough-balance", resp);
default: return opUnknownFailure(resp, body)
}
}
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.BadGateway: return opKnownFailure("tan-failed", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -472,7 +477,7 @@ export class TalerCoreBankHttpClient {
case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
case HttpStatusCode.Conflict: return opKnownFailure("already-confirmed", resp);
//FIXME: should be 404 ?
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -492,11 +497,22 @@ export class TalerCoreBankHttpClient {
});
switch (resp.status) {
case HttpStatusCode.NoContent: return opEmptySuccess()
- case HttpStatusCode.Forbidden: return opKnownFailure("wrong-tan-or-credential", resp);
case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.Conflict: return opKnownFailure("cashout-address-changed", resp);
- //FIXME: should be 404 ?
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ // case HttpStatusCode.Forbidden: return opKnownFailure("wrong-tan-or-credential", resp);
+ case HttpStatusCode.Conflict: {
+ const body = await resp.json()
+ const details = codecForTalerErrorDetail().decode(body)
+ switch (details.code) {
+ case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT: return opKnownFailure("already-aborted", resp);
+ case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return opKnownFailure("no-cashout-payto", resp);
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT: return opKnownFailure("no-enough-balance", resp);
+ case TalerErrorCode.BANK_BAD_CONVERSION: return opKnownFailure("incorrect-exchange-rate", resp);
+ // case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED: return opKnownFailure("no-enough-balance", resp);
+ default: return opUnknownFailure(resp, body)
+ }
+ }
+ case HttpStatusCode.TooManyRequests: return opKnownFailure("too-many-attempts", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -518,7 +534,7 @@ export class TalerCoreBankHttpClient {
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashouts())
case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", resp);;
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -538,7 +554,7 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutStatusResponse())
case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -559,7 +575,7 @@ export class TalerCoreBankHttpClient {
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForGlobalCashouts())
case HttpStatusCode.NoContent: return opFixedSuccess({ cashouts: [] });
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
@@ -574,24 +590,61 @@ export class TalerCoreBankHttpClient {
url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit))
}
if (conversion.credit) {
- url.searchParams.set("amount_debit", Amounts.stringify(conversion.credit))
+ url.searchParams.set("amount_credit", Amounts.stringify(conversion.credit))
}
const resp = await this.httpLib.fetch(url.href, {
method: "GET",
});
switch (resp.status) {
case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutConversionResponse())
- // FIXME: error code for
- // * the requested currency was not supported
- // * the calculation is not correct
- case HttpStatusCode.BadRequest: return opKnownFailure("wrong-calculation", resp);
- case HttpStatusCode.NotFound: return opKnownFailure("not-supported", resp);
- //FIXME: should be 404 ?
- case HttpStatusCode.ServiceUnavailable: return opKnownFailure("cashout-not-supported", resp);
+ case HttpStatusCode.BadRequest: {
+ const body = await resp.json()
+ const details = codecForTalerErrorDetail().decode(body)
+ switch (details.code) {
+ case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownFailure("missing-params", resp);
+ case TalerErrorCode.GENERIC_PARAMETER_MALFORMED : return opKnownFailure("wrong-calculation", resp);
+ case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownFailure("wrong-currency", resp);
+ default: return opUnknownFailure(resp, body)
+ }
+ }
+ case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
default: return opUnknownFailure(resp, await resp.text())
}
}
+ /**
+ * https://docs.taler.net/core/api-corebank.html#get--cashin-rate
+ *
+ */
+ async getCashinRate(conversion: { debit?: AmountJson, credit?: AmountJson }) {
+ const url = new URL(`cashin-rate`, this.baseUrl);
+ if (conversion.debit) {
+ url.searchParams.set("amount_debit", Amounts.stringify(conversion.debit))
+ }
+ if (conversion.credit) {
+ url.searchParams.set("amount_credit", Amounts.stringify(conversion.credit))
+ }
+ const resp = await this.httpLib.fetch(url.href, {
+ method: "GET",
+ });
+ switch (resp.status) {
+ case HttpStatusCode.Ok: return opSuccess(resp, codecForCashinConversionResponse())
+ case HttpStatusCode.BadRequest: {
+ const body = await resp.json()
+ const details = codecForTalerErrorDetail().decode(body)
+ switch (details.code) {
+ case TalerErrorCode.GENERIC_PARAMETER_MISSING: return opKnownFailure("missing-params", resp);
+ case TalerErrorCode.GENERIC_PARAMETER_MALFORMED : return opKnownFailure("wrong-calculation", resp);
+ case TalerErrorCode.GENERIC_CURRENCY_MISMATCH: return opKnownFailure("wrong-currency", resp);
+ default: return opUnknownFailure(resp, body)
+ }
+ }
+ case HttpStatusCode.Conflict: return opKnownFailure("amount-too-small", resp);
+ case HttpStatusCode.NotImplemented: return opKnownFailure("cashout-not-supported", resp);
+ default: return opUnknownFailure(resp, await resp.text())
+ }
+ }
//
// MONITOR
//
diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts
index 77004cf5b..f6542abcd 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -357,13 +357,13 @@ export const codecForBankAccountTransactionsResponse =
export const codecForBankAccountTransactionInfo =
(): Codec<TalerCorebankApi.BankAccountTransactionInfo> =>
buildCodecForObject<TalerCorebankApi.BankAccountTransactionInfo>()
- .property("amount", codecForAmountString())
.property("creditor_payto_uri", codecForPaytoString())
- .property("date", codecForTimestamp)
.property("debtor_payto_uri", codecForPaytoString())
+ .property("amount", codecForAmountString())
.property("direction", codecForEither(codecForConstString("debit"), codecForConstString("credit")))
- .property("row_id", codecForNumber())
.property("subject", codecForString())
+ .property("row_id", codecForNumber())
+ .property("date", codecForTimestamp)
.build("TalerCorebankApi.BankAccountTransactionInfo");
export const codecForBankAccountCreateWithdrawalResponse =
@@ -376,8 +376,8 @@ export const codecForBankAccountCreateWithdrawalResponse =
export const codecForBankAccountGetWithdrawalResponse =
(): Codec<TalerCorebankApi.BankAccountGetWithdrawalResponse> =>
buildCodecForObject<TalerCorebankApi.BankAccountGetWithdrawalResponse>()
- .property("aborted", codecForBoolean())
.property("amount", codecForAmountString())
+ .property("aborted", codecForBoolean())
.property("confirmation_done", codecForBoolean())
.property("selected_exchange_account", codecOptional(codecForPaytoString()))
.property("selected_reserve_pub", codecOptional(codecForString()))
@@ -397,6 +397,13 @@ export const codecForCashoutConversionResponse =
.property("amount_debit", codecForAmountString())
.build("TalerCorebankApi.CashoutConversionResponse");
+export const codecForCashinConversionResponse =
+ (): Codec<TalerCorebankApi.CashinConversionResponse> =>
+ buildCodecForObject<TalerCorebankApi.CashinConversionResponse>()
+ .property("amount_credit", codecForAmountString())
+ .property("amount_debit", codecForAmountString())
+ .build("TalerCorebankApi.CashinConversionResponse");
+
export const codecForCashouts =
(): Codec<TalerCorebankApi.Cashouts> =>
buildCodecForObject<TalerCorebankApi.Cashouts>()
@@ -407,7 +414,7 @@ export const codecForCashoutInfo =
(): Codec<TalerCorebankApi.CashoutInfo> =>
buildCodecForObject<TalerCorebankApi.CashoutInfo>()
.property("cashout_id", codecForString())
- .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"),))
+ .property("status", codecForEither(codecForConstString("pending"), codecForConstString("aborted"), codecForConstString("confirmed"),))
.build("TalerCorebankApi.CashoutInfo");
export const codecForGlobalCashouts =
@@ -421,7 +428,7 @@ export const codecForGlobalCashoutInfo =
buildCodecForObject<TalerCorebankApi.GlobalCashoutInfo>()
.property("cashout_id", codecForString())
.property("username", codecForString())
- .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed"),))
+ .property("status", codecForEither(codecForConstString("pending"), codecForConstString("aborted"), codecForConstString("confirmed"),))
.build("TalerCorebankApi.GlobalCashoutInfo");
export const codecForCashoutStatusResponse =
@@ -431,8 +438,8 @@ export const codecForCashoutStatusResponse =
.property("amount_debit", codecForAmountString())
.property("confirmation_time", codecForTimestamp)
.property("creation_time", codecForTimestamp)
- .property("credit_payto_uri", codecForPaytoString())
- .property("status", codecForEither(codecForConstString("pending"), codecForConstString("confirmed")))
+ // .property("credit_payto_uri", codecForPaytoString())
+ .property("status", codecForEither(codecForConstString("pending"), codecForConstString("aborted"), codecForConstString("confirmed")))
.property("subject", codecForString())
.build("TalerCorebankApi.CashoutStatusResponse");
@@ -448,28 +455,34 @@ export const codecForConversionRatesResponse =
export const codecForMonitorResponse = (): Codec<TalerCorebankApi.MonitorResponse> => buildCodecForUnion<TalerCorebankApi.MonitorResponse>()
.discriminateOn("type")
- .alternative("just-payouts", codecForMonitorResponseJustPayout())
- .alternative("with-cashout", codecForMonitorResponseWithCashout())
+ .alternative("no-conversions", codecForMonitorNoConversion())
+ .alternative("with-conversions", codecForMonitorWithCashout())
.build("TalerWireGatewayApi.IncomingBankTransaction");
-export const codecForMonitorResponseJustPayout =
- (): Codec<TalerCorebankApi.MonitorJustPayouts> =>
- buildCodecForObject<TalerCorebankApi.MonitorJustPayouts>()
- .property("type", codecForConstString("just-payouts"))
- .property("talerPayoutCount", codecForNumber())
- .property("talerPayoutInternalVolume", codecForAmountString())
+export const codecForMonitorNoConversion =
+ (): Codec<TalerCorebankApi.MonitorNoConversion> =>
+ buildCodecForObject<TalerCorebankApi.MonitorNoConversion>()
+ .property("type", codecForConstString("no-conversions"))
+ .property("talerInCount", codecForNumber())
+ .property("talerInVolume", codecForAmountString())
+ .property("talerOutCount", codecForNumber())
+ .property("talerOutVolume", codecForAmountString())
.build("TalerCorebankApi.MonitorJustPayouts");
-export const codecForMonitorResponseWithCashout =
- (): Codec<TalerCorebankApi.MonitorWithCashout> =>
- buildCodecForObject<TalerCorebankApi.MonitorWithCashout>()
- .property("type", codecForConstString("with-cashout"))
- .property("cashinCount", (codecForNumber()))
- .property("cashinExternalVolume", (codecForAmountString()))
- .property("cashoutCount", (codecForNumber()))
- .property("cashoutExternalVolume", (codecForAmountString()))
- .property("talerPayoutCount", codecForNumber())
- .property("talerPayoutInternalVolume", codecForAmountString())
+export const codecForMonitorWithCashout =
+ (): Codec<TalerCorebankApi.MonitorWithConversion> =>
+ buildCodecForObject<TalerCorebankApi.MonitorWithConversion>()
+ .property("type", codecForConstString("with-conversions"))
+ .property("cashinCount", codecForNumber())
+ .property("cashinFiatVolume", codecForAmountString())
+ .property("cashinRegionalVolume", codecForAmountString())
+ .property("cashoutCount", codecForNumber())
+ .property("cashoutFiatVolume", codecForAmountString())
+ .property("cashoutRegionalVolume", codecForAmountString())
+ .property("talerInCount", codecForNumber())
+ .property("talerInVolume", codecForAmountString())
+ .property("talerOutCount", codecForNumber())
+ .property("talerOutVolume", codecForAmountString())
.build("TalerCorebankApi.MonitorWithCashout");
export const codecForBankVersion =
@@ -697,7 +710,6 @@ const codecForDecimalNumber = codecForNumber
enum TanChannel {
SMS = "sms",
EMAIL = "email",
- FILE = "file"
}
export namespace TalerWireGatewayApi {
@@ -1174,7 +1186,7 @@ export namespace TalerCorebankApi {
// If present, change the is_exchange configuration.
// See RegisterAccountRequest
- is_exchange?: boolean;
+ is_taler_exchange?: boolean;
// If present, change the max debit allowed for this user
// Only admin can change this property.
@@ -1252,10 +1264,15 @@ export namespace TalerCorebankApi {
export interface CashoutRequest {
+ // Nonce to make the request idempotent. Requests with the same
+ // request_uid that differ in any of the other fields
+ // are rejected.
+ request_uid: ShortHashCode;
+
// Optional subject to associate to the
// cashout operation. This data will appear
// as the incoming wire transfer subject in
- // the user's external bank account.
+ // the user's fiat bank account.
subject?: string;
// That is the plain amount that the user specified
@@ -1301,6 +1318,15 @@ export namespace TalerCorebankApi {
amount_credit: AmountString;
}
+ export interface CashinConversionResponse {
+ // Amount that the user will get deducted from their fiat
+ // bank account, according to the 'amount_credit' value.
+ amount_debit: AmountString;
+ // Amount that the user will receive in their regional
+ // bank account, according to 'amount_debit'.
+ amount_credit: AmountString;
+ }
+
export interface Cashouts {
// Every string represents a cash-out operation ID.
cashouts: CashoutInfo[];
@@ -1308,7 +1334,7 @@ export namespace TalerCorebankApi {
export interface CashoutInfo {
cashout_id: string;
- status: "pending" | "confirmed";
+ status: "pending" | "aborted" | "confirmed";
}
export interface GlobalCashouts {
// Every string represents a cash-out operation ID.
@@ -1317,11 +1343,11 @@ export namespace TalerCorebankApi {
export interface GlobalCashoutInfo {
cashout_id: string;
username: string;
- status: "pending" | "confirmed";
+ status: "pending" | "aborted" | "confirmed";
}
export interface CashoutStatusResponse {
- status: "pending" | "confirmed";
+ status: "pending" | "aborted" | "confirmed";
// Amount debited to the internal
// regional currency bank account.
@@ -1335,7 +1361,7 @@ export namespace TalerCorebankApi {
// Fiat bank account that will receive the cashed out amount.
// Specified as a payto URI.
- credit_payto_uri: PaytoString;
+ // credit_payto_uri: PaytoString;
// Time when the cashout was created.
creation_time: Timestamp;
@@ -1365,59 +1391,72 @@ export namespace TalerCorebankApi {
}
export type MonitorResponse =
- | MonitorJustPayouts
- | MonitorWithCashout;
+ | MonitorNoConversion
+ | MonitorWithConversion;
// Monitoring stats when conversion is not supported
- export interface MonitorJustPayouts {
- type: "just-payouts";
+ export interface MonitorNoConversion {
+ type: "no-conversions";
+
+ // How many payments were made to a Taler exchange by another
+ // bank account.
+ talerInCount: number;
- // This number identifies how many payments were made by a
- // Taler exchange to a merchant bank account in the internal
- // currency, in the timeframe specified in the request.
- talerPayoutCount: number;
+ // Overall volume that has been paid to a Taler
+ // exchange by another bank account.
+ talerInVolume: AmountString;
- // This amount accounts the overall *internal* currency that
- // has been paid by a Taler exchange to a merchant internal
- // bank account, in the timeframe specified in the request.
- talerPayoutInternalVolume: AmountString;
+ // How many payments were made by a Taler exchange to another
+ // bank account.
+ talerOutCount: number;
+
+ // Overall volume that has been paid by a Taler
+ // exchange to another bank account.
+ talerOutVolume: AmountString;
}
// Monitoring stats when conversion is supported
- export interface MonitorWithCashout {
- type: "with-cashout";
+ export interface MonitorWithConversion {
+ type: "with-conversions";
- // This number identifies how many cashin operations
- // took place in the timeframe specified in the request.
- // This number corresponds to how many withdrawals have
- // been initiated by a wallet owner. Note: wallet owners
+ // How many cashin operations were confirmed by a
+ // wallet owner. Note: wallet owners
// are NOT required to be customers of the libeufin-bank.
cashinCount: number;
- // This amount accounts how much external currency has been
- // spent to withdraw Taler coins in the internal currency.
- // The exact amount of internal currency being created can be
- // calculated using the advertised conversion rates.
- cashinExternalVolume: AmountString;
+ // Overall regional currency that has been paid by the regional admin account
+ // to regional bank accounts to fulfill all the confirmed cashin operations.
+ cashinRegionalVolume: AmountString;
+
+ // Overall fiat currency that has been paid to the fiat admin account
+ // by fiat bank accounts to fulfill all the confirmed cashin operations.
+ cashinFiatVolume: AmountString;
- // This number identifies how many cashout operations were
- // confirmed in the timeframe speficied in the request.
+ // How many cashout operations were confirmed.
cashoutCount: number;
- // This amount corresponds to how much *external* currency was
- // paid by the libeufin-bank administrator to fulfill all the
- // confirmed cashouts related to the timeframe specified in the
- // request.
- cashoutExternalVolume: AmountString;
-
- // This number identifies how many payments were made by a
- // Taler exchange to a merchant bank account in the internal
- // currency, in the timeframe specified in the request.
- talerPayoutCount: number;
-
- // This amount accounts the overall *internal* currency that
- // has been paid by a Taler exchange to a merchant internal
- // bank account, in the timeframe specified in the request.
- talerPayoutInternalVolume: AmountString;
+ // Overall regional currency that has been paid to the regional admin account
+ // by fiat bank accounts to fulfill all the confirmed cashout operations.
+ cashoutRegionalVolume: AmountString;
+
+ // Overall fiat currency that has been paid by the fiat admin account
+ // to fiat bank accounts to fulfill all the confirmed cashout operations.
+ cashoutFiatVolume: AmountString;
+
+ // How many payments were made to a Taler exchange by another
+ // bank account.
+ talerInCount: number;
+
+ // Overall volume that has been paid to a Taler
+ // exchange by another bank account.
+ talerInVolume: AmountString;
+
+ // How many payments were made by a Taler exchange to another
+ // bank account.
+ talerOutCount: number;
+
+ // Overall volume that has been paid by a Taler
+ // exchange to another bank account.
+ talerOutVolume: AmountString;
}