commit 60fa2f8c6fe2d1902624052746c2a7a83d2f4c65
parent 2bea1081cd7ee9a5d8195069d1857eede7f4bbb8
Author: Sebastian <sebasjm@gmail.com>
Date: Fri, 24 Oct 2025 20:39:33 -0300
kyc
Diffstat:
4 files changed, 160 insertions(+), 256 deletions(-)
diff --git a/packages/kyc-ui/src/pages/FillForm.tsx b/packages/kyc-ui/src/pages/FillForm.tsx
@@ -24,7 +24,7 @@ import {
import {
AcceptTermOfServiceContext,
Attention,
- Button,
+ ButtonBetter,
ErrorsSummary,
FormMetadata,
FormUI,
@@ -34,8 +34,8 @@ import {
preloadedForms,
useAsyncAsHook,
useExchangeApiContext,
- useLocalNotificationHandler,
- useTranslationContext,
+ useLocalNotificationBetter,
+ useTranslationContext
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useFormMeta } from "../../../web-util/src/hooks/useForm.js";
@@ -115,7 +115,7 @@ function ShowForm({
onComplete: () => void;
}): VNode {
const { lib } = useExchangeApiContext();
- const [notification, withErrorHandler] = useLocalNotificationHandler();
+ const [notification, safeFunctionHandler] = useLocalNotificationBetter();
const [preferences] = usePreferences();
const { i18n } = useTranslationContext();
@@ -125,33 +125,29 @@ function ShowForm({
design,
} = useFormMeta<FormType>(theForm, formContext, {});
const validatedForm = status.status !== "ok" ? undefined : status.result;
+ if (validatedForm) {
+ validatedForm[TalerFormAttributes.FORM_ID] = theForm.id;
+ validatedForm[TalerFormAttributes.FORM_VERSION] = theForm.version;
+ validatedForm[TalerFormAttributes.FORM_CONTEXT] = formContext;
+ }
- const submitHandler =
- validatedForm === undefined
- ? undefined
- : withErrorHandler(
- async () => {
- validatedForm[TalerFormAttributes.FORM_ID] = theForm.id;
- validatedForm[TalerFormAttributes.FORM_VERSION] = theForm.version;
- validatedForm[TalerFormAttributes.FORM_CONTEXT] = formContext;
- return lib.exchange.uploadKycForm(reqId, validatedForm);
- },
- (res) => {
- onComplete();
- },
- (fail) => {
- switch (fail.case) {
- case HttpStatusCode.PayloadTooLarge:
- return i18n.str`The form is too big for the server, try uploading smaller files.`;
- case HttpStatusCode.NotFound:
- return i18n.str`The account was not found`;
- case HttpStatusCode.Conflict:
- return i18n.str`Officer disabled or more recent decision was already submitted.`;
- default:
- assertUnreachable(fail);
- }
- },
- );
+ const submit = safeFunctionHandler(
+ lib.exchange.uploadKycForm,
+ !validatedForm ? undefined : [reqId, validatedForm],
+ );
+ submit.onSuccess = onComplete;
+ submit.onFail = (fail) => {
+ switch (fail.case) {
+ case HttpStatusCode.PayloadTooLarge:
+ return i18n.str`The form is too big for the server, try uploading smaller files.`;
+ case HttpStatusCode.NotFound:
+ return i18n.str`The account was not found`;
+ case HttpStatusCode.Conflict:
+ return i18n.str`Officer disabled or more recent decision was already submitted.`;
+ default:
+ assertUnreachable(fail);
+ }
+ };
return (
<div class="rounded-lg bg-white px-5 py-6 shadow m-4">
@@ -181,14 +177,13 @@ function ShowForm({
>
<i18n.Translate>Cancel</i18n.Translate>
</button>
- <Button
+ <ButtonBetter
type="submit"
- handler={submitHandler}
- disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ onClick={submit}
>
<i18n.Translate>Submit</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
{!status.errors ? undefined : <ErrorsSummary errors={status.errors} />}
</div>
diff --git a/packages/kyc-ui/src/pages/Start.tsx b/packages/kyc-ui/src/pages/Start.tsx
@@ -23,11 +23,12 @@ import {
} from "@gnu-taler/taler-util";
import {
Attention,
+ ButtonBetter,
ErrorLoading,
Loading,
LocalNotificationBanner,
useExchangeApiContext,
- useLocalNotificationHandler,
+ useLocalNotificationBetter,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
@@ -168,9 +169,26 @@ export function Start({ token }: Props): VNode {
function LinkGenerator({ req }: { req: KycRequirementInformation }): VNode {
const { i18n } = useTranslationContext();
- const [notification, , notify] = useLocalNotificationHandler();
+ const [notification, safeFunctionHandler] = useLocalNotificationBetter();
const { lib } = useExchangeApiContext();
+ const start = safeFunctionHandler((id: string) =>
+ lib.exchange.startExternalKycProcess(id),
+ );
+ start.onFail = (fail) => {
+ switch (fail.case) {
+ case HttpStatusCode.NotFound:
+ return i18n.str`not found`;
+ case HttpStatusCode.Conflict:
+ return i18n.str`conflict`;
+ case HttpStatusCode.PayloadTooLarge:
+ return i18n.str`payload is too large`;
+ }
+ };
+ start.onSuccess = (success) => {
+ setRedirectUrl(success.body.redirect_url);
+ return i18n.str`Link generated, you can proceed.`;
+ };
const [redirectUrl, setRedirectUrl] = useState<string>();
const row = (
<Fragment>
@@ -218,56 +236,12 @@ function LinkGenerator({ req }: { req: KycRequirementInformation }): VNode {
) : (
// href={redirectUrl}
<p class="text-sm font-semibold leading-6 text-gray-900">
- <button
- onClick={async () => {
- const res = await lib.exchange.startExternalKycProcess(
- req.id!,
- );
- if (res.type === "ok") {
- setRedirectUrl(res.body.redirect_url);
- notify({
- type: "info",
- title: i18n.str`Link generated, you can proceed.`,
- when: AbsoluteTime.now(),
- });
- } else {
- switch (res.case) {
- case HttpStatusCode.NotFound: {
- notify({
- type: "error",
- title: i18n.str`could not create redirect url`,
- description: i18n.str`not found`,
- when: AbsoluteTime.now(),
- });
- break;
- }
- case HttpStatusCode.Conflict: {
- notify({
- type: "error",
- title: i18n.str`could not create redirect url`,
- description: i18n.str`conflict`,
- when: AbsoluteTime.now(),
- });
- break;
- }
- case HttpStatusCode.PayloadTooLarge: {
- notify({
- type: "error",
- title: i18n.str`could not create redirect url`,
- description: i18n.str`payload too large`,
- when: AbsoluteTime.now(),
- });
- break;
- }
- }
- }
- }}
- >
+ <ButtonBetter onClick={start}>
<span class="absolute inset-x-0 -top-px bottom-0"></span>
<i18n.Translate context="KYC_REQUIREMENT_LINK_DESCRIPTION">
{req.description}
</i18n.Translate>
- </button>
+ </ButtonBetter>
</p>
)}
</div>
diff --git a/packages/kyc-ui/src/pages/TriggerForms.tsx b/packages/kyc-ui/src/pages/TriggerForms.tsx
@@ -20,7 +20,7 @@ import {
preloadedForms,
UIHandlerId,
useFormMeta,
- useLocalNotificationHandler,
+ useLocalNotificationBetter,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
@@ -35,8 +35,7 @@ type Props = {
export function TriggerForms({ formId }: Props): VNode {
const { i18n } = useTranslationContext();
- const [notification, withErrorHandler, notify] =
- useLocalNotificationHandler();
+ const [notification, safeFunctionHandler] = useLocalNotificationBetter();
const pf = preloadedForms(i18n);
diff --git a/packages/kyc-ui/src/pages/TriggerKyc.tsx b/packages/kyc-ui/src/pages/TriggerKyc.tsx
@@ -14,31 +14,33 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import {
- AbsoluteTime,
AccessToken,
AmountJson,
Amounts,
+ AmountString,
assertUnreachable,
createNewWalletKycAccount,
eddsaGetPublic,
encodeCrock,
HttpStatusCode,
+ opFixedSuccess,
+ opKnownFailure,
signKycAuth,
signWalletAccountSetup,
- WalletKycRequest,
+ WalletKycRequest
} from "@gnu-taler/taler-util";
import {
- Button,
+ ButtonBetter,
FormMetadata,
FormUI,
LocalNotificationBanner,
UIHandlerId,
useExchangeApiContext,
- useLocalNotificationHandler,
+ useLocalNotificationBetter,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
-import { useEffect, useMemo, useState } from "preact/hooks";
+import { useMemo } from "preact/hooks";
import { useFormMeta } from "../../../web-util/src/hooks/useForm.js";
type FormType = {
@@ -51,10 +53,8 @@ type Props = {
export function TriggerKyc({ onKycStarted }: Props): VNode {
const { i18n } = useTranslationContext();
- const [notification, withErrorHandler, notify] =
- useLocalNotificationHandler();
+ const [notification, safeFunctionHandler] = useLocalNotificationBetter();
const { config, lib } = useExchangeApiContext();
- const [kycAccount, setKycAccount] = useState<string>();
const theForm: FormMetadata = {
id: "asd",
@@ -98,101 +98,66 @@ export function TriggerKyc({ onKycStarted }: Props): VNode {
return createNewWalletKycAccount(extraEntropy);
}, [1]);
- useEffect(() => {
- if (!kycAccount) return;
- const paytoHash = kycAccount;
- async function check() {
- const { signingKey } = await accountPromise;
- const merchantPub = eddsaGetPublic(signingKey);
- const accountOwnerSig = encodeCrock(signKycAuth(signingKey));
- const result = await lib.exchange.checkKycStatus({
- accountPub: encodeCrock(merchantPub),
- accountSig: accountOwnerSig,
- paytoHash,
- });
- switch (result.case) {
- case "ok":
- console.log("empty body");
- break;
- case HttpStatusCode.Ok:
- case HttpStatusCode.Accepted:
- onKycStarted(result.body.access_token);
- break;
- case HttpStatusCode.Forbidden: {
- notify({
- type: "error",
- title: i18n.str`could not create token`,
- description: i18n.str`access denied`,
- when: AbsoluteTime.now(),
- });
- break;
- }
- case HttpStatusCode.NotFound: {
- notify({
- type: "error",
- title: i18n.str`could not create token`,
- description: i18n.str`not found`,
- when: AbsoluteTime.now(),
- });
- break;
- }
- case HttpStatusCode.Conflict: {
- notify({
- type: "error",
- title: i18n.str`could not create token`,
- description: i18n.str`conflict`,
- when: AbsoluteTime.now(),
- });
- break;
- }
+ const send = safeFunctionHandler(
+ async (balance: AmountString) => {
+ const account = await accountPromise;
+ const limit: WalletKycRequest = {
+ balance,
+ reserve_pub: account.id,
+ reserve_sig: encodeCrock(
+ signWalletAccountSetup(account.signingKey, balance),
+ ),
+ };
+ const resp = await lib.exchange.notifyKycBalanceLimit(limit);
+ if (resp.type === "ok") {
+ return opKnownFailure(HttpStatusCode.Ok);
}
- }
- check();
- }, [kycAccount]);
-
- function triggerAmount(amount: AmountJson) {
- return withErrorHandler(
- async () => {
- const account = await accountPromise;
- const balance = Amounts.stringify(amount);
- const limit: WalletKycRequest = {
- balance,
- reserve_pub: account.id,
- reserve_sig: encodeCrock(
- signWalletAccountSetup(account.signingKey, balance),
- ),
- };
- return lib.exchange.notifyKycBalanceLimit(limit);
- },
- (res) => {
- notify({
- type: "info",
- title: i18n.str`No kyc required`,
- when: AbsoluteTime.now(),
+ if (resp.case === HttpStatusCode.UnavailableForLegalReasons) {
+ const paytoHash = resp.body.h_payto;
+ const { signingKey } = await accountPromise;
+ const merchantPub = eddsaGetPublic(signingKey);
+ const accountOwnerSig = encodeCrock(signKycAuth(signingKey));
+ const result = await lib.exchange.checkKycStatus({
+ accountPub: encodeCrock(merchantPub),
+ accountSig: accountOwnerSig,
+ paytoHash,
});
- },
- (fail) => {
- switch (fail.case) {
- case HttpStatusCode.Forbidden:
- return i18n.str`Access denied trying to test balance.`;
- case HttpStatusCode.UnavailableForLegalReasons:
- setKycAccount(fail.body.h_payto);
- return i18n.str`Unavailable For Legal Reasons`;
- default:
- assertUnreachable(fail);
+ if (result.type === "ok") {
+ return opKnownFailure(HttpStatusCode.Ok);
}
- },
- );
- }
-
- const sendFormValue =
+ if (
+ result.type === "fail" &&
+ (result.case === HttpStatusCode.Accepted ||
+ result.case === HttpStatusCode.Ok)
+ ) {
+ return opFixedSuccess(result.body);
+ }
+ return result;
+ }
+ return resp;
+ },
theForm === undefined || status.status === "fail"
? undefined
- : triggerAmount(status.result.amount);
+ : [Amounts.stringify(status.result.amount)],
+ );
- if (kycAccount) {
- return <div>loading...</div>;
- }
+ send.onSuccess = (success) => {
+ onKycStarted(success.body.access_token);
+ };
+ send.onFail = (fail) => {
+ switch (fail.case) {
+ case HttpStatusCode.Ok:
+ return i18n.str`No kyc triggered.`;
+ case HttpStatusCode.Forbidden:
+ return i18n.str`Forbidden.`;
+ case HttpStatusCode.NotFound:
+ return i18n.str`Not found.`;
+ case HttpStatusCode.Conflict:
+ return i18n.str`Conflict.`;
+ default:
+ assertUnreachable(fail);
+ }
+ };
return (
<div class="rounded-lg bg-white px-5 py-6 shadow m-4">
@@ -208,14 +173,13 @@ export function TriggerKyc({ onKycStarted }: Props): VNode {
>
<i18n.Translate>Cancel</i18n.Translate>
</button>
- <Button
+ <ButtonBetter
type="submit"
- handler={sendFormValue}
- // disabled={!submitHandler}
+ onClick={send}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Submit</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div class="grid grid-cols-1 gap-x-8 gap-y-4 ">
@@ -227,172 +191,144 @@ export function TriggerKyc({ onKycStarted }: Props): VNode {
</i18n.Translate>
</p>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000000`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000000`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger TOPS Terms of service</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000010`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000010`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger GLS onboarding</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000020`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000020`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.1</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000030`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000030`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.4</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000040`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000040`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.5</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000050`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000050`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.9</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000060`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000060`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.11</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000070`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000070`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.12</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000080`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000080`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.13</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000090`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000090`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.14</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000100`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000100`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.15</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000110`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000110`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Challenger test</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000120`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000120`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.9 customer</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
<div>
- <Button
+ <ButtonBetter
type="submit"
- handler={triggerAmount(
- Amounts.parseOrThrow(`${config.config.currency}:1000130`),
- )}
+ onClick={send.lambda(() => [`${config.config.currency}:1000130`])}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Trigger VQF 902.9 officer</i18n.Translate>
- </Button>
+ </ButtonBetter>
</div>
</div>
</div>