diff options
author | Sebastian <sebasjm@gmail.com> | 2023-09-22 18:34:49 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-09-25 14:50:44 -0300 |
commit | 15af6c619de70336bcdfbabbd32b9d93aabefc5b (patch) | |
tree | 5dff83b07f9ffcb26cd4eb595f9e80f549ae25b5 | |
parent | 5640f0a67dcc31fa2b5fa0992abca8a55bc00dd8 (diff) |
towards new core bank api
19 files changed, 3293 insertions, 3158 deletions
diff --git a/packages/demobank-ui/src/components/Routing.tsx b/packages/demobank-ui/src/components/Routing.tsx index 90d2d4c48..d51bd01eb 100644 --- a/packages/demobank-ui/src/components/Routing.tsx +++ b/packages/demobank-ui/src/components/Routing.tsx @@ -27,6 +27,7 @@ import { Test } from "../pages/Test.js"; import { useBackendContext } from "../context/backend.js"; import { LoginForm } from "../pages/LoginForm.js"; import { AdminHome } from "../pages/admin/Home.js"; +import { bankUiSettings } from "../settings.js"; export function Routing(): VNode { const history = createHashHistory(); @@ -46,6 +47,10 @@ export function Routing(): VNode { )} /> <Route + path="/public-accounts" + component={() => <PublicHistoriesPage />} + /> + <Route path="/operation/:wopid" component={({ wopid }: { wopid: string }) => ( <WithdrawalOperationPage @@ -53,22 +58,21 @@ export function Routing(): VNode { onContinue={() => { route("/account"); }} - // onLoadNotOk={() => { - // route("/account"); - // }} - /> - )} - /> - <Route - path="/register" - component={() => ( - <RegistrationPage - onComplete={() => { - route("/account"); - }} /> )} /> + {bankUiSettings.allowRegistrations && + <Route + path="/register" + component={() => ( + <RegistrationPage + onComplete={() => { + route("/account"); + }} + /> + )} + /> + } <Route default component={Redirect} to="/login" /> </Router> </BankFrame> @@ -94,16 +98,6 @@ export function Routing(): VNode { component={() => <PublicHistoriesPage />} /> <Route - path="/register" - component={() => ( - <RegistrationPage - onComplete={() => { - route("/account"); - }} - /> - )} - /> - <Route path="/account" component={() => { if (isUserAdministrator) { diff --git a/packages/demobank-ui/src/declaration.d.ts b/packages/demobank-ui/src/declaration.d.ts index 462287c59..a9573fbcd 100644 --- a/packages/demobank-ui/src/declaration.d.ts +++ b/packages/demobank-ui/src/declaration.d.ts @@ -99,11 +99,6 @@ type Amount = string; type UUID = string; type Integer = number; -interface Balance { - amount: Amount; - credit_debit_indicator: "credit" | "debit"; -} - namespace SandboxBackend { export interface Config { // Name of this API, always "circuit". @@ -126,7 +121,7 @@ namespace SandboxBackend { } export interface SandboxError { - error: SandboxErrorDetail; + error?: SandboxErrorDetail; } interface SandboxErrorDetail { // String enum classifying the error. @@ -152,26 +147,12 @@ namespace SandboxBackend { UtilError = "util-error", } - namespace Access { - interface PublicAccountsResponse { - publicAccounts: PublicAccount[]; - } - interface PublicAccount { - iban: string; - balance: string; - // The account name _and_ the username of the - // Sandbox customer that owns such a bank account. - accountLabel: string; - } - interface BankAccountBalanceResponse { - // Available balance on the account. - balance: Balance; - // payto://-URI of the account. (New) - paytoUri: string; - // Number indicating the max debit allowed for the requesting user. - debitThreshold: Amount; - } + type EmailAddress = string; + type PhoneNumber = string; + + namespace CoreBank { + interface BankAccountCreateWithdrawalRequest { // Amount to withdraw. amount: Amount; @@ -243,11 +224,144 @@ namespace SandboxBackend { amount?: string; } - interface BankRegistrationRequest { + interface RegisterAccountRequest { + // Username username: string; + // Password. password: string; + + // Legal name of the account owner + name: string; + + // Defaults to false. + is_public?: boolean; + + // Is this a taler exchange account? + // If true: + // - incoming transactions to the account that do not + // have a valid reserve public key are automatically + // - the account provides the taler-wire-gateway-api endpoints + // Defaults to false. + is_taler_exchange?: boolean; + + // Addresses where to send the TAN for transactions. + // Currently only used for cashouts. + // If missing, cashouts will fail. + // In the future, might be used for other transactions + // as well. + challenge_contact_data?: ChallengeContactData; + + // 'payto' address pointing a bank account + // external to the libeufin-bank. + // Payments will be sent to this bank account + // when the user wants to convert the local currency + // back to fiat currency outside libeufin-bank. + cashout_payto_uri?: string; + + // Internal payto URI of this bank account. + // Used mostly for testing. + internal_payto_uri?: string; + } + interface ChallengeContactData { + + // E-Mail address + email?: EmailAddress; + + // Phone number. + phone?: PhoneNumber; + } + + interface AccountReconfiguration { + + // Addresses where to send the TAN for transactions. + // Currently only used for cashouts. + // If missing, cashouts will fail. + // In the future, might be used for other transactions + // as well. + challenge_contact_data?: ChallengeContactData; + + // 'payto' address pointing a bank account + // external to the libeufin-bank. + // Payments will be sent to this bank account + // when the user wants to convert the local currency + // back to fiat currency outside libeufin-bank. + cashout_address?: string; + + // Legal name associated with $username. + // When missing, the old name is kept. + name?: string; + + // If present, change the is_exchange configuration. + // See RegisterAccountRequest + is_exchange?: boolean; + } + + + interface AccountPasswordChange { + + // New password. + new_password: string; + } + interface PublicAccountsResponse { + public_accounts: PublicAccount[]; + } + interface PublicAccount { + payto_uri: string; + + balance: Balance; + + // The account name (=username) of the + // libeufin-bank account. + account_name: string; + } + + interface ListBankAccountsResponse { + accounts: AccountMinimalData[]; + } + // interface Balance { + // amount: Amount; + // credit_debit_indicator: "credit" | "debit"; + // } + type Balance = Amount + interface AccountMinimalData { + // Username + username: string; + + // Legal name of the account owner. + name: string; + + // current balance of the account + balance: Balance; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + } + + interface AccountData { + // Legal name of the account owner. + name: string; + + // Available balance on the account. + balance: Balance; + + // payto://-URI of the account. + payto_uri: string; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + + contact_data?: ChallengeContactData; + + // 'payto' address pointing the bank account + // where to send cashouts. This field is optional + // because not all the accounts are required to participate + // in the merchants' circuit. One example is the exchange: + // that never cashouts. Registering these accounts can + // be done via the access API. + cashout_payto_uri?: string; } + } namespace Circuit { diff --git a/packages/demobank-ui/src/hooks/access.ts b/packages/demobank-ui/src/hooks/access.ts index af8381135..13fee71f0 100644 --- a/packages/demobank-ui/src/hooks/access.ts +++ b/packages/demobank-ui/src/hooks/access.ts @@ -44,13 +44,13 @@ export function useAccessAPI(): AccessAPI { const account = state.username; const createWithdrawal = async ( - data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest, + data: SandboxBackend.CoreBank.BankAccountCreateWithdrawalRequest, ): Promise< - HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse> + HttpResponseOk<SandboxBackend.CoreBank.BankAccountCreateWithdrawalResponse> > => { const res = - await request<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>( - `access-api/accounts/${account}/withdrawals`, + await request<SandboxBackend.CoreBank.BankAccountCreateWithdrawalResponse>( + `accounts/${account}/withdrawals`, { method: "POST", data, @@ -60,10 +60,10 @@ export function useAccessAPI(): AccessAPI { return res; }; const createTransaction = async ( - data: SandboxBackend.Access.CreateBankAccountTransactionCreate, + data: SandboxBackend.CoreBank.CreateBankAccountTransactionCreate, ): Promise<HttpResponseOk<void>> => { const res = await request<void>( - `access-api/accounts/${account}/transactions`, + `accounts/${account}/transactions`, { method: "POST", data, @@ -74,7 +74,7 @@ export function useAccessAPI(): AccessAPI { return res; }; const deleteAccount = async (): Promise<HttpResponseOk<void>> => { - const res = await request<void>(`access-api/accounts/${account}`, { + const res = await request<void>(`accounts/${account}`, { method: "DELETE", contentType: "json", }); @@ -94,7 +94,7 @@ export function useAccessAnonAPI(): AccessAnonAPI { const { request } = useAuthenticatedBackend(); const abortWithdrawal = async (id: string): Promise<HttpResponseOk<void>> => { - const res = await request<void>(`access-api/withdrawals/${id}/abort`, { + const res = await request<void>(`accounts/withdrawals/${id}/abort`, { method: "POST", contentType: "json", }); @@ -104,7 +104,7 @@ export function useAccessAnonAPI(): AccessAnonAPI { const confirmWithdrawal = async ( id: string, ): Promise<HttpResponseOk<void>> => { - const res = await request<void>(`access-api/withdrawals/${id}/confirm`, { + const res = await request<void>(`withdrawals/${id}/confirm`, { method: "POST", contentType: "json", }); @@ -122,10 +122,10 @@ export function useTestingAPI(): TestingAPI { const mutateAll = useMatchMutate(); const { request: noAuthRequest } = usePublicBackend(); const register = async ( - data: SandboxBackend.Access.BankRegistrationRequest, + data: SandboxBackend.CoreBank.RegisterAccountRequest, ): Promise<HttpResponseOk<void>> => { // FIXME: This API is deprecated. The normal account registration API should be used instead. - const res = await noAuthRequest<void>(`access-api/testing/register`, { + const res = await noAuthRequest<void>(`accounts`, { method: "POST", data, contentType: "json", @@ -139,18 +139,18 @@ export function useTestingAPI(): TestingAPI { export interface TestingAPI { register: ( - data: SandboxBackend.Access.BankRegistrationRequest, + data: SandboxBackend.CoreBank.RegisterAccountRequest, ) => Promise<HttpResponseOk<void>>; } export interface AccessAPI { createWithdrawal: ( - data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest, + data: SandboxBackend.CoreBank.BankAccountCreateWithdrawalRequest, ) => Promise< - HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse> + HttpResponseOk<SandboxBackend.CoreBank.BankAccountCreateWithdrawalResponse> >; createTransaction: ( - data: SandboxBackend.Access.CreateBankAccountTransactionCreate, + data: SandboxBackend.CoreBank.CreateBankAccountTransactionCreate, ) => Promise<HttpResponseOk<void>>; deleteAccount: () => Promise<HttpResponseOk<void>>; } @@ -167,15 +167,15 @@ export interface InstanceTemplateFilter { export function useAccountDetails( account: string, ): HttpResponse< - SandboxBackend.Access.BankAccountBalanceResponse, + SandboxBackend.CoreBank.AccountData, SandboxBackend.SandboxError > { const { fetcher } = useAuthenticatedBackend(); const { data, error } = useSWR< - HttpResponseOk<SandboxBackend.Access.BankAccountBalanceResponse>, + HttpResponseOk<SandboxBackend.CoreBank.AccountData>, RequestError<SandboxBackend.SandboxError> - >([`access-api/accounts/${account}`], fetcher, { + >([`accounts/${account}`], fetcher, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, @@ -187,28 +187,8 @@ export function useAccountDetails( keepPreviousData: true, }); - //FIXME: remove optional when libeufin sandbox has implemented the feature - if (data && typeof data.data.debitThreshold === "undefined") { - data.data.debitThreshold = "0"; - } - //FIXME: sandbox server should return amount string if (data) { - const isAmount = Amounts.parse(data.data.debitThreshold); - if (isAmount) { - //server response with correct format - return data; - } - const { currency } = Amounts.parseOrThrow(data.data.balance.amount); - const clone = structuredClone(data); - - const theNumber = Number.parseInt(data.data.debitThreshold, 10); - const value = Number.isNaN(theNumber) ? 0 : theNumber; - clone.data.debitThreshold = Amounts.stringify({ - currency, - value: value, - fraction: 0, - }); - return clone; + return data; } if (error) return error.cause; return { loading: true }; @@ -218,15 +198,15 @@ export function useAccountDetails( export function useWithdrawalDetails( wid: string, ): HttpResponse< - SandboxBackend.Access.BankAccountGetWithdrawalResponse, + SandboxBackend.CoreBank.BankAccountGetWithdrawalResponse, SandboxBackend.SandboxError > { const { fetcher } = useAuthenticatedBackend(); const { data, error } = useSWR< - HttpResponseOk<SandboxBackend.Access.BankAccountGetWithdrawalResponse>, + HttpResponseOk<SandboxBackend.CoreBank.BankAccountGetWithdrawalResponse>, RequestError<SandboxBackend.SandboxError> - >([`access-api/withdrawals/${wid}`], fetcher, { + >([`withdrawals/${wid}`], fetcher, { refreshInterval: 1000, refreshWhenHidden: false, revalidateOnFocus: false, @@ -248,15 +228,15 @@ export function useTransactionDetails( account: string, tid: string, ): HttpResponse< - SandboxBackend.Access.BankAccountTransactionInfo, + SandboxBackend.CoreBank.BankAccountTransactionInfo, SandboxBackend.SandboxError > { - const { fetcher } = useAuthenticatedBackend(); + const { paginatedFetcher } = useAuthenticatedBackend(); const { data, error } = useSWR< - HttpResponseOk<SandboxBackend.Access.BankAccountTransactionInfo>, + HttpResponseOk<SandboxBackend.CoreBank.BankAccountTransactionInfo>, RequestError<SandboxBackend.SandboxError> - >([`access-api/accounts/${account}/transactions/${tid}`], fetcher, { + >([`accounts/${account}/transactions/${tid}`], paginatedFetcher, { refreshInterval: 0, refreshWhenHidden: false, revalidateOnFocus: false, @@ -281,7 +261,7 @@ interface PaginationFilter { export function usePublicAccounts( args?: PaginationFilter, ): HttpResponsePaginated< - SandboxBackend.Access.PublicAccountsResponse, + SandboxBackend.CoreBank.PublicAccountsResponse, SandboxBackend.SandboxError > { const { paginatedFetcher } = usePublicBackend(); @@ -293,13 +273,13 @@ export function usePublicAccounts( error: afterError, isValidating: loadingAfter, } = useSWR< - HttpResponseOk<SandboxBackend.Access.PublicAccountsResponse>, + HttpResponseOk<SandboxBackend.CoreBank.PublicAccountsResponse>, RequestError<SandboxBackend.SandboxError> - >([`access-api/public-accounts`, args?.page, PAGE_SIZE], paginatedFetcher); + >([`public-accounts`, args?.page, PAGE_SIZE], paginatedFetcher); const [lastAfter, setLastAfter] = useState< HttpResponse< - SandboxBackend.Access.PublicAccountsResponse, + SandboxBackend.CoreBank.PublicAccountsResponse, SandboxBackend.SandboxError > >({ loading: true }); @@ -312,7 +292,7 @@ export function usePublicAccounts( // if the query returns less that we ask, then we have reach the end or beginning const isReachingEnd = - afterData && afterData.data.publicAccounts.length < PAGE_SIZE; + afterData && afterData.data.public_accounts.length < PAGE_SIZE; const isReachingStart = false; const pagination = { @@ -320,7 +300,7 @@ export function usePublicAccounts( isReachingStart, loadMore: () => { if (!afterData || isReachingEnd) return; - if (afterData.data.publicAccounts.length < MAX_RESULT_SIZE) { + if (afterData.data.public_accounts.length < MAX_RESULT_SIZE) { setPage(page + 1); } }, @@ -329,12 +309,12 @@ export function usePublicAccounts( }, }; - const publicAccounts = !afterData + const public_accounts = !afterData ? [] - : (afterData || lastAfter).data.publicAccounts; - if (loadingAfter) return { loading: true, data: { publicAccounts } }; + : (afterData || lastAfter).data.public_accounts; + if (loadingAfter) return { loading: true, data: { public_accounts } }; if (afterData) { - return { ok: true, data: { publicAccounts }, ...pagination }; + return { ok: true, data: { public_accounts }, ...pagination }; } return { loading: true }; } @@ -349,7 +329,7 @@ export function useTransactions( account: string, args?: PaginationFilter, ): HttpResponsePaginated< - SandboxBackend.Access.BankAccountTransactionsResponse, + SandboxBackend.CoreBank.BankAccountTransactionsResponse, SandboxBackend.SandboxError > { const { paginatedFetcher } = useAuthenticatedBackend(); @@ -361,10 +341,10 @@ export function useTransactions( error: afterError, isValidating: loadingAfter, } = useSWR< - HttpResponseOk<SandboxBackend.Access.BankAccountTransactionsResponse>, + HttpResponseOk<SandboxBackend.CoreBank.BankAccountTransactionsResponse>, RequestError<SandboxBackend.SandboxError> >( - [`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE], + [`accounts/${account}/transactions`, args?.page, PAGE_SIZE], paginatedFetcher, { refreshInterval: 0, refreshWhenHidden: false, @@ -378,7 +358,7 @@ export function useTransactions( const [lastAfter, setLastAfter] = useState< HttpResponse< - SandboxBackend.Access.BankAccountTransactionsResponse, + SandboxBackend.CoreBank.BankAccountTransactionsResponse, SandboxBackend.SandboxError > >({ loading: true }); diff --git a/packages/demobank-ui/src/hooks/backend.ts b/packages/demobank-ui/src/hooks/backend.ts index 9d32db4b8..f2be90f08 100644 --- a/packages/demobank-ui/src/hooks/backend.ts +++ b/packages/demobank-ui/src/hooks/backend.ts @@ -310,7 +310,7 @@ export function useAuthenticatedBackend(): useBackendType { ]): Promise<HttpResponseOk<T>> { return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds, - params: { page, size }, + params: { delta: size, start: size * page }, }); }, [baseUrl, creds], diff --git a/packages/demobank-ui/src/hooks/useCredentialsChecker.ts b/packages/demobank-ui/src/hooks/useCredentialsChecker.ts index b76754ffe..05954348f 100644 --- a/packages/demobank-ui/src/hooks/useCredentialsChecker.ts +++ b/packages/demobank-ui/src/hooks/useCredentialsChecker.ts @@ -9,20 +9,25 @@ export function useCredentialsChecker() { //while merchant backend doesn't have a login endpoint async function requestNewLoginToken( username: string, - password: AccessToken, + password: string, ): Promise<LoginResult> { const data: LoginTokenRequest = { - scope: "write", + scope: "readwrite" as "write", //FIX: different than merchant duration: { - d_us: "forever" + // d_us: "forever" //FIX: should return shortest + d_us: 1000 * 60 * 60 * 23 }, refreshable: true, } try { const response = await request<LoginTokenSuccessResponse>(baseUrl, `accounts/${username}/token`, { method: "POST", - token: password, - data + basicAuth: { + username: username, + password, + }, + data, + contentType: "json" }); return { valid: true, token: response.data.token, expiration: response.data.expiration }; } catch (error) { diff --git a/packages/demobank-ui/src/pages/AccountPage/index.ts b/packages/demobank-ui/src/pages/AccountPage/index.ts index 81eeb4a03..ba9b85710 100644 --- a/packages/demobank-ui/src/pages/AccountPage/index.ts +++ b/packages/demobank-ui/src/pages/AccountPage/index.ts @@ -60,7 +60,7 @@ export namespace State { export interface InvalidIban { status: "invalid-iban", - error: HttpResponseOk<SandboxBackend.Access.BankAccountBalanceResponse>; + error: HttpResponseOk<SandboxBackend.CoreBank.AccountData>; } export interface UserNotFound { diff --git a/packages/demobank-ui/src/pages/AccountPage/state.ts b/packages/demobank-ui/src/pages/AccountPage/state.ts index 1a1475c0d..b12afbf9e 100644 --- a/packages/demobank-ui/src/pages/AccountPage/state.ts +++ b/packages/demobank-ui/src/pages/AccountPage/state.ts @@ -40,7 +40,7 @@ export function useComponentState({ account, goToBusinessAccount, goToConfirmOpe }; } //logout if there is any error, not if loading - backend.logOut(); + // backend.logOut(); if (result.status === HttpStatusCode.NotFound) { notifyError(i18n.str`Username or account label "${account}" not found`, undefined); return { @@ -55,9 +55,13 @@ export function useComponentState({ account, goToBusinessAccount, goToConfirmOpe } const { data } = result; - const balance = Amounts.parseOrThrow(data.balance.amount); - const debitThreshold = Amounts.parseOrThrow(data.debitThreshold); - const payto = parsePaytoUri(data.paytoUri); + + // FIXME: balance + // const balance = Amounts.parseOrThrow(data.balance.amount); + const balance = Amounts.parseOrThrow(data.balance); + + const debitThreshold = Amounts.parseOrThrow(data.debit_threshold); + const payto = parsePaytoUri(data.payto_uri); if (!payto || !payto.isKnown || (payto.targetType !== "iban" && payto.targetType !== "x-taler-bank")) { return { @@ -66,7 +70,9 @@ export function useComponentState({ account, goToBusinessAccount, goToConfirmOpe }; } - const balanceIsDebit = data.balance.credit_debit_indicator == "debit"; + // FIXME: balance + const balanceIsDebit = true; + // data.balance.credit_debit_indicator == "debit"; const limit = balanceIsDebit ? Amounts.sub(debitThreshold, balance).amount : Amounts.add(balance, debitThreshold).amount; diff --git a/packages/demobank-ui/src/pages/AccountPage/views.tsx b/packages/demobank-ui/src/pages/AccountPage/views.tsx index 23a815bd8..b3996c5fc 100644 --- a/packages/demobank-ui/src/pages/AccountPage/views.tsx +++ b/packages/demobank-ui/src/pages/AccountPage/views.tsx @@ -27,7 +27,7 @@ import { useSettings } from "../../hooks/settings.js"; export function InvalidIbanView({ error }: State.InvalidIban) { return ( - <div>Payto from server is not valid "{error.data.paytoUri}"</div> + <div>Payto from server is not valid "{error.data.payto_uri}"</div> ); } diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx index 5bfaa63ec..a1414544e 100644 --- a/packages/demobank-ui/src/pages/BankFrame.tsx +++ b/packages/demobank-ui/src/pages/BankFrame.tsx @@ -458,15 +458,14 @@ function WelcomeAccount({ account }: { account: string }): VNode { const result = useAccountDetails(account); if (!result.ok) return <div /> - // const account = "Sebastian" - const payto = parsePaytoUri(result.data.paytoUri) + const payto = parsePaytoUri(result.data.payto_uri) if (!payto) return <div /> const accountNumber = !payto.isKnown ? undefined : payto.targetType === "iban" ? payto.iban : payto.targetType === "x-taler-bank" ? payto.account : undefined; return <i18n.Translate> Welcome, {account} {accountNumber !== undefined ? <span> - (<a href={result.data.paytoUri}>{accountNumber}</a> <CopyButton getContent={() => result.data.paytoUri} />) + (<a href={result.data.payto_uri}>{accountNumber}</a> <CopyButton getContent={() => result.data.payto_uri} />) </span> : <Fragment />}! </i18n.Translate> @@ -477,9 +476,12 @@ function AccountBalance({ account }: { account: string }): VNode { const result = useAccountDetails(account); if (!result.ok) return <div /> + // FIXME: balance return <div> - {Amounts.currencyOf(result.data.balance.amount)} + {Amounts.currencyOf(result.data.balance)} + {Amounts.stringifyValue(result.data.balance)} + {/* {Amounts.currencyOf(result.data.balance.amount)} {result.data.balance.credit_debit_indicator === "debit" ? "-" : ""} - {Amounts.stringifyValue(result.data.balance.amount)} + {Amounts.stringifyValue(result.data.balance.amount)} */} </div> } diff --git a/packages/demobank-ui/src/pages/HomePage.tsx b/packages/demobank-ui/src/pages/HomePage.tsx index 8d5e1f3b9..d80a57d21 100644 --- a/packages/demobank-ui/src/pages/HomePage.tsx +++ b/packages/demobank-ui/src/pages/HomePage.tsx @@ -120,8 +120,8 @@ export function handleNotOkResult( ) => VNode { return function handleNotOkResult2<T>( result: - | HttpResponsePaginated<T, SandboxBackend.SandboxError> - | HttpResponse<T, SandboxBackend.SandboxError>, + | HttpResponsePaginated<T, SandboxBackend.SandboxError | undefined> + | HttpResponse<T, SandboxBackend.SandboxError| undefined>, ): VNode { if (result.loading) return <Loading />; if (!result.ok) { @@ -139,7 +139,7 @@ export function handleNotOkResult( notify({ type: "error", title: i18n.str`Could not load due to a client error`, - description: errorData.error.description as TranslatedString, + description: errorData?.error?.description as TranslatedString, debug: JSON.stringify(result), }); break; @@ -148,7 +148,7 @@ export function handleNotOkResult( notify({ type: "error", title: i18n.str`Server returned with error`, - description: result.payload.error.description as TranslatedString, + description: result.payload?.error?.description as TranslatedString, debug: JSON.stringify(result.payload), }); break; diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx b/packages/demobank-ui/src/pages/LoginForm.tsx index f6ea0e1d1..0d4bd1261 100644 --- a/packages/demobank-ui/src/pages/LoginForm.tsx +++ b/packages/demobank-ui/src/pages/LoginForm.tsx @@ -31,12 +31,13 @@ import { useCredentialsCheckerOld } from "../hooks/backend.js"; */ export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode { const backend = useBackendContext(); - const [username, setUsername] = useState<string | undefined>(); + const currentUser = backend.state.status === "loggedIn" ? backend.state.username : undefined + const [username, setUsername] = useState<string | undefined>(currentUser); const [password, setPassword] = useState<string | undefined>(); const { i18n } = useTranslationContext(); - // const { requestNewLoginToken, refreshLoginToken } = useCredentialsChecker(); + const { requestNewLoginToken, refreshLoginToken } = useCredentialsChecker(); - const testLogin = useCredentialsCheckerOld(); + // const testLogin = useCredentialsCheckerOld(); const ref = useRef<HTMLInputElement>(null); useEffect(function focusInput() { ref.current?.focus(); @@ -46,8 +47,8 @@ export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode { const errors = undefinedIfEmpty({ username: !username ? i18n.str`Missing username` - : !USERNAME_REGEX.test(username) - ? i18n.str`Use letters and numbers only, and start with a lowercase letter` + // : !USERNAME_REGEX.test(username) + // ? i18n.str`Use letters and numbers only, and start with a lowercase letter` : undefined, password: !password ? i18n.str`Missing password` : undefined, }) ?? busy; @@ -59,19 +60,18 @@ export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode { async function doLogin() { if (!username || !password) return; setBusy({}) - const testResult = await testLogin(username, password); - if (testResult.valid) { + const result = await requestNewLoginToken(username, password); + if (result.valid) { backend.logIn({ username, password }); } else { - if (testResult.requestError) { - const { cause } = testResult; - switch (cause.type) { - case ErrorType.CLIENT: { - if (cause.status === HttpStatusCode.Unauthorized) { - saveError({ - title: i18n.str`Wrong credentials for "${username}"`, - }); - } else + const { cause } = result; + switch (cause.type) { + case ErrorType.CLIENT: { + if (cause.status === HttpStatusCode.Unauthorized) { + saveError({ + title: i18n.str`Wrong credentials for "${username}"`, + }); + } else if (cause.status === HttpStatusCode.NotFound) { saveError({ title: i18n.str`Account not found`, @@ -79,50 +79,44 @@ export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode { } else { saveError({ title: i18n.str`Could not load due to a client error`, - description: cause.payload.error.description, + // description: cause.payload.error.description, debug: JSON.stringify(cause.payload), }); } - break; - } - case ErrorType.SERVER: { - saveError({ - title: i18n.str`Server had a problem, try again later or report.`, - description: cause.payload.error.description, - debug: JSON.stringify(cause.payload), - }); - break; - } - case ErrorType.TIMEOUT: { - saveError({ - title: i18n.str`Request timeout, try again later.`, - }); - break; - } - case ErrorType.UNREADABLE: { - saveError({ - title: i18n.str`Unexpected error.`, - description: `Response from ${cause.info?.url} is unreadable, http status: ${cause.status}` as TranslatedString, - debug: JSON.stringify(cause), - }); - break; - } - default: { - saveError({ - title: i18n.str`Unexpected error, please report.`, - description: `Diagnostic from ${cause.info?.url} is "${cause.message}"` as TranslatedString, - debug: JSON.stringify(cause), - }); - break; - } + break; + } + case ErrorType.SERVER: { + saveError({ + title: i18n.str`Server had a problem, try again later or report.`, + // description: cause.payload.error.description, + debug: JSON.stringify(cause.payload), + }); + break; + } + case ErrorType.TIMEOUT: { + saveError({ + title: i18n.str`Request timeout, try again later.`, + }); + break; + } + case ErrorType.UNREADABLE: { + saveError({ + title: i18n.str`Unexpected error.`, + description: `Response from ${cause.info?.url} is unreadable, http status: ${cause.status}` as TranslatedString, + debug: JSON.stringify(cause), + }); + break; + } + default: { + saveError({ + title: i18n.str`Unexpected error, please report.`, + description: `Diagnostic from ${cause.info?.url} is "${cause.message}"` as TranslatedString, + debug: JSON.stringify(cause), + }); + break; } - } else { - saveError({ - title: i18n.str`Unexpected error, please report.`, - debug: JSON.stringify(testResult.error), - }); } - backend.logOut(); + // backend.logOut(); } setPassword(undefined); setBusy(undefined) diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx index 03bdb78b7..680368919 100644 --- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx +++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx @@ -36,8 +36,8 @@ export function PublicHistoriesPage({}: Props): VNode { const result = usePublicAccounts(); const [showAccount, setShowAccount] = useState( - result.ok && result.data.publicAccounts.length > 0 - ? result.data.publicAccounts[0].accountLabel + result.ok && result.data.public_accounts.length > 0 + ? result.data.public_accounts[0].account_name : undefined, ); @@ -51,9 +51,9 @@ export function PublicHistoriesPage({}: Props): VNode { const accountsBar = []; // Ask story of all the public accounts. - for (const account of data.publicAccounts) { - logger.trace("Asking transactions for", account.accountLabel); - const isSelected = account.accountLabel == showAccount; + for (const account of data.public_accounts) { + logger.trace("Asking transactions for", account.account_name); + const isSelected = account.account_name == showAccount; accountsBar.push( <li class={ @@ -65,13 +65,13 @@ export function PublicHistoriesPage({}: Props): VNode { <a href="#" class="pure-menu-link" - onClick={() => setShowAccount(account.accountLabel)} + onClick={() => setShowAccount(account.account_name)} > - {account.accountLabel} + {account.account_name} </a> </li>, ); - txs[account.accountLabel] = <Transactions account={account.accountLabel} />; + txs[account.account_name] = <Transactions account={account.account_name} />; } return ( diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx index f972e0380..8221457bf 100644 --- a/packages/demobank-ui/src/pages/RegistrationPage.tsx +++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx @@ -53,6 +53,7 @@ export const USERNAME_REGEX = /^[a-z][a-zA-Z0-9-]*$/; function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { const backend = useBackendContext(); const [username, setUsername] = useState<string | undefined>(); + const [name, setName] = useState<string | undefined>(); const [password, setPassword] = useState<string | undefined>(); const [repeatPassword, setRepeatPassword] = useState<string | undefined>(); @@ -60,6 +61,9 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { const { i18n } = useTranslationContext(); const errors = undefinedIfEmpty({ + name: !name + ? i18n.str`Missing name` + : undefined, username: !username ? i18n.str`Missing username` : !USERNAME_REGEX.test(username) @@ -74,9 +78,9 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { }); async function doRegistrationStep() { - if (!username || !password) return; + if (!username || !password || !name) return; try { - await register({ username, password }); + await register({ name, username, password }); setUsername(undefined); backend.logIn({ username, password }); onComplete(); @@ -97,13 +101,13 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { ? error.message : JSON.stringify(error)) as TranslatedString ) -} + } } setPassword(undefined); setRepeatPassword(undefined); -} + } - async function delay(ms: number):Promise<void> { + async function delay(ms: number): Promise<void> { return new Promise((resolve) => { setTimeout(() => { resolve(undefined); @@ -117,14 +121,15 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { setUsername(undefined); setPassword(undefined); setRepeatPassword(undefined); - await register({ username: user, password: pass }); - backend.logIn({ username: user, password: pass }); + const username = `_${user.first}-${user.second}_` + await register({ username, name: `${user.first} ${user.second}`, password: pass }); + backend.logIn({ username, password: pass }); onComplete(); } catch (error) { if (error instanceof RequestError) { if (tries > 0) { await delay(200) - await doRandomRegistration(tries-1) + await doRandomRegistration(tries - 1) } else { notify( buildRequestErrorMessage(i18n, error.cause, { @@ -142,7 +147,7 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { ? error.message : JSON.stringify(error)) as TranslatedString ) -} + } } } @@ -257,17 +262,19 @@ function RegistrationForm({ onComplete }: { onComplete: () => void }): VNode { </form> - <p class="mt-10 text-center text-sm text-gray-500 border-t"> - <button type="submit" - class="flex mt-4 w-full justify-center rounded-md bg-green-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" - onClick={(e) => { - e.preventDefault() - doRandomRegistration() - }} - > - <i18n.Translate>Create a random user</i18n.Translate> - </button> - </p> + {bankUiSettings.allowRandomAccountCreation && + <p class="mt-10 text-center text-sm text-gray-500 border-t"> + <button type="submit" + class="flex mt-4 w-full justify-center rounded-md bg-green-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" + onClick={(e) => { + e.preventDefault() + doRandomRegistration() + }} + > + <i18n.Translate>Create a random user</i18n.Translate> + </button> + </p> + } </div> </div> diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx index 8dbdd9da6..e16825527 100644 --- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx +++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx @@ -59,27 +59,41 @@ function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: { }, [focus]); if (!!settings.currentWithdrawalOperationId) { - return <div class="rounded-md bg-yellow-50 ring-yellow-2 p-4"> - <div class="flex"> - <div class="flex-shrink-0"> - <svg class="h-5 w-5 text-yellow-300" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> - <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" /> - </svg> - </div> - <div class="ml-3"> - <h3 class="text-sm font-bold text-yellow-800"> - <i18n.Translate>There is an operation already</i18n.Translate> - </h3> - <div class="mt-2 text-sm text-yellow-700"> - <p> - <i18n.Translate> - To complete or cancel the operation click <a class="font-semibold text-yellow-700 hover:text-yellow-600" href={`#/operation/${settings.currentWithdrawalOperationId}`}>here</a> - </i18n.Translate> - </p> + return <div> + + <div class="rounded-md bg-yellow-50 ring-yellow-2 p-4"> + <div class="flex"> + <div class="flex-shrink-0"> + <svg class="h-5 w-5 text-yellow-300" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> + <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" /> + </svg> + </div> + <div class="ml-3"> + <h3 class="text-sm font-bold text-yellow-800"> + <i18n.Translate>There is an operation already</i18n.Translate> + </h3> + <div class="mt-2 text-sm text-yellow-700"> + <p> + <i18n.Translate> + To complete or cancel the operation click <a class="font-semibold text-yellow-700 hover:text-yellow-600" href={`#/operation/${settings.currentWithdrawalOperationId}`}>here</a> + </i18n.Translate> + </p> + </div> + + </div> </div> + </div > + <div class="flex justify-end gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8 " > + <button type="button" class="text-sm font-semibold leading-6 text-gray-900 bg-white p-2 rounded-sm" + onClick={() => { + updateSettings("currentWithdrawalOperationId", undefined) + onCancel() + }} + > + <i18n.Translate>Cancel</i18n.Translate> + </button> </div> </div> - </div > } const trimmedAmountStr = amountStr?.trim(); diff --git a/packages/demobank-ui/src/pages/admin/Account.tsx b/packages/demobank-ui/src/pages/admin/Account.tsx index 90ddd611d..d368c4319 100644 --- a/packages/demobank-ui/src/pages/admin/Account.tsx +++ b/packages/demobank-ui/src/pages/admin/Account.tsx @@ -16,9 +16,14 @@ export function AdminAccount({ onRegister }: { onRegister: () => void }): VNode return handleNotOkResult(i18n, onRegister)(result); } const { data } = result; - const balance = Amounts.parseOrThrow(data.balance.amount); - const debitThreshold = Amounts.parseOrThrow(result.data.debitThreshold); - const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit"; + + //FIXME: libeufin does not follow the spec + const balance = Amounts.parseOrThrow(data.balance); + const balanceIsDebit = true; + // const balance = Amounts.parseOrThrow(data.balance.amount); + // const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit"; + + const debitThreshold = Amounts.parseOrThrow(result.data.debit_threshold); const limit = balanceIsDebit ? Amounts.sub(debitThreshold, balance).amount : Amounts.add(balance, debitThreshold).amount; diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx index 1e5370afc..63a7c79f3 100644 --- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx @@ -41,7 +41,9 @@ export function RemoveAccount({ if (focus) ref.current?.focus(); }, [focus]); - const balance = Amounts.parse(result.data.balance.amount); + //FIXME: libeufin does not follow the spec + const balance = Amounts.parse(result.data.balance); + // const balance = Amounts.parse(result.data.balance.amount); if (!balance) { return <div>there was an error reading the balance</div>; } diff --git a/packages/demobank-ui/src/pages/business/Home.tsx b/packages/demobank-ui/src/pages/business/Home.tsx index f5f77a3ea..427cfc656 100644 --- a/packages/demobank-ui/src/pages/business/Home.tsx +++ b/packages/demobank-ui/src/pages/business/Home.tsx @@ -201,13 +201,13 @@ function useRatiosAndFeeConfigWithChangeDetection(): HttpResponse< (result.data.name !== oldResult.name || result.data.version !== oldResult.version || result.data.ratios_and_fees.buy_at_ratio !== - oldResult.ratios_and_fees.buy_at_ratio || + oldResult.ratios_and_fees.buy_at_ratio || result.data.ratios_and_fees.buy_in_fee !== - oldResult.ratios_and_fees.buy_in_fee || + oldResult.ratios_and_fees.buy_in_fee || result.data.ratios_and_fees.sell_at_ratio !== - oldResult.ratios_and_fees.sell_at_ratio || + oldResult.ratios_and_fees.sell_at_ratio || result.data.ratios_and_fees.sell_out_fee !== - oldResult.ratios_and_fees.sell_out_fee || + oldResult.ratios_and_fees.sell_out_fee || result.data.fiat_currency !== oldResult.fiat_currency); return { @@ -236,10 +236,14 @@ function CreateCashout({ if (!ratiosResult.ok) return onLoadNotOk(ratiosResult); const config = ratiosResult.data; - const balance = Amounts.parseOrThrow(result.data.balance.amount); - const debitThreshold = Amounts.parseOrThrow(result.data.debitThreshold); + //FIXME: libeufin does not follow the spec + const balance = Amounts.parseOrThrow(result.data.balance); + const balanceIsDebit = true; + // const balance = Amounts.parseOrThrow(result.data.balance.amount); + // const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit"; + + const debitThreshold = Amounts.parseOrThrow(result.data.debit_threshold); const zero = Amounts.zeroOfCurrency(balance.currency); - const balanceIsDebit = result.data.balance.credit_debit_indicator == "debit"; const limit = balanceIsDebit ? Amounts.sub(debitThreshold, balance).amount : Amounts.add(balance, debitThreshold).amount; @@ -250,15 +254,14 @@ function CreateCashout({ const sellFee = !config.ratios_and_fees.sell_out_fee ? zero : Amounts.parseOrThrow( - `${balance.currency}:${config.ratios_and_fees.sell_out_fee}`, - ); + `${balance.currency}:${config.ratios_and_fees.sell_out_fee}`, + ); const fiatCurrency = config.fiat_currency; if (!sellRate || sellRate < 0) return <div>error rate</div>; const amount = Amounts.parseOrThrow( - `${!form.isDebit ? fiatCurrency : balance.currency}:${ - !form.amount ? "0" : form.amount + `${!form.isDebit ? fiatCurrency : balance.currency}:${!form.amount ? "0" : form.amount }`, ); @@ -273,10 +276,10 @@ function CreateCashout({ error instanceof RequestError ? buildRequestErrorMessage(i18n, error.cause) : { - type: "error", - title: i18n.str`Could not estimate the cashout`, - description: error.message as TranslatedString - }, + type: "error", + title: i18n.str`Could not estimate the cashout`, + description: error.message as TranslatedString + }, ); }); } else { @@ -289,10 +292,10 @@ function CreateCashout({ error instanceof RequestError ? buildRequestErrorMessage(i18n, error.cause) : { - type: "error", - title: i18n.str`Could not estimate the cashout`, - description: error.message, - }, + type: "error", + title: i18n.str`Could not estimate the cashout`, + description: error.message, + }, ); }); } @@ -307,14 +310,14 @@ function CreateCashout({ amount: !form.amount ? i18n.str`required` : !amount - ? i18n.str`could not be parsed` - : Amounts.cmp(limit, calc.debit) === -1 - ? i18n.str`balance is not enough` - : Amounts.cmp(calc.beforeFee, sellFee) === -1 - ? i18n.str`the total amount to transfer does not cover the fees` - : Amounts.isZero(calc.credit) - ? i18n.str`the total transfer at destination will be zero` - : undefined, + ? i18n.str`could not be parsed` + : Amounts.cmp(limit, calc.debit) === -1 + ? i18n.str`balance is not enough` + : Amounts.cmp(calc.beforeFee, sellFee) === -1 + ? i18n.str`the total amount to transfer does not cover the fees` + : Amounts.isZero(calc.credit) + ? i18n.str`the total transfer at destination will be zero` + : undefined, channel: !form.channel ? i18n.str`required` : undefined, }); @@ -341,7 +344,7 @@ function CreateCashout({ {form.isDebit ? i18n.str`Amount to send` : i18n.str`Amount to receive`} - + </label> <div style={{ display: "flex" }}> <Amount @@ -520,12 +523,12 @@ function CreateCashout({ status === HttpStatusCode.BadRequest ? i18n.str`The exchange rate was incorrectly applied` : status === HttpStatusCode.Forbidden - ? i18n.str`A institutional user tried the operation` - : status === HttpStatusCode.Conflict - ? i18n.str`Need a contact data where to send the TAN` - : status === HttpStatusCode.PreconditionFailed - ? i18n.str`The account does not have sufficient funds` - : undefined, + ? i18n.str`A institutional user tried the operation` + : status === HttpStatusCode.Conflict + ? i18n.str`Need a contact data where to send the TAN` + : status === HttpStatusCode.PreconditionFailed + ? i18n.str`The account does not have sufficient funds` + : undefined, onServerError: (status) => status === HttpStatusCode.ServiceUnavailable ? i18n.str`The bank does not support the TAN channel for this operation` @@ -539,7 +542,7 @@ function CreateCashout({ ? error.message : JSON.stringify(error)) as TranslatedString ) - } + } } }} > @@ -665,8 +668,8 @@ export function ShowCashoutDetails({ status === HttpStatusCode.NotFound ? i18n.str`Cashout not found. It may be also mean that it was already aborted.` : status === HttpStatusCode.PreconditionFailed - ? i18n.str`Cashout was already confimed` - : undefined, + ? i18n.str`Cashout was already confimed` + : undefined, }), ); } else { @@ -676,7 +679,7 @@ export function ShowCashoutDetails({ ? error.message : JSON.stringify(error)) as TranslatedString ) - } + } } }} > @@ -702,12 +705,12 @@ export function ShowCashoutDetails({ status === HttpStatusCode.NotFound ? i18n.str`Cashout not found. It may be also mean that it was already aborted.` : status === HttpStatusCode.PreconditionFailed - ? i18n.str`Cashout was already confimed` - : status === HttpStatusCode.Conflict - ? i18n.str`Confirmation failed. Maybe the user changed their cash-out address between the creation and the confirmation` - : status === HttpStatusCode.Forbidden - ? i18n.str`Invalid code` - : undefined, + ? i18n.str`Cashout was already confimed` + : status === HttpStatusCode.Conflict + ? i18n.str`Confirmation failed. Maybe the user changed their cash-out address between the creation and the confirmation` + : status === HttpStatusCode.Forbidden + ? i18n.str`Invalid code` + : undefined, }), ); } else { @@ -717,7 +720,7 @@ export function ShowCashoutDetails({ ? error.message : JSON.stringify(error)) as TranslatedString ) - } + } } }} > diff --git a/packages/demobank-ui/src/pages/rnd.ts b/packages/demobank-ui/src/pages/rnd.ts index 8c9bae875..32c3a934f 100644 --- a/packages/demobank-ui/src/pages/rnd.ts +++ b/packages/demobank-ui/src/pages/rnd.ts @@ -1,2890 +1,2895 @@ import { createEddsaKeyPair, encodeCrock, getRandomBytes } from "@gnu-taler/taler-util" +import { bankUiSettings } from "../settings.js" const noun = [ - "people", - "history", - "way", - "art", - "world", - "information", - "map", - "two", - "family", - "government", - "health", - "system", - "computer", - "meat", - "year", - "thanks", - "music", - "person", - "reading", - "method", - "data", - "food", - "understanding", - "theory", - "law", - "bird", - "literature", - "problem", - "software", - "control", - "knowledge", - "power", - "ability", - "economics", - "love", - "internet", - "television", - "science", - "library", - "nature", - "fact", - "product", - "idea", - "temperature", - "investment", - "area", - "society", - "activity", - "story", - "industry", - "media", - "thing", - "oven", - "community", - "definition", - "safety", - "quality", - "development", - "language", - "management", - "player", - "variety", - "video", - "week", - "security", - "country", - "exam", - "movie", - "organization", - "equipment", - "physics", - "analysis", - "policy", - "series", - "thought", - "basis", - "boyfriend", - "direction", - "strategy", - "technology", - "army", - "camera", - "freedom", - "paper", - "environment", - "child", - "instance", - "month", - "truth", - "marketing", - "university", - "writing", - "article", - "department", - "difference", - "goal", - "news", - "audience", - "fishing", - "growth", - "income", - "marriage", - "user", - "combination", - "failure", - "meaning", - "medicine", - "philosophy", - "teacher", - "communication", - "night", - "chemistry", - "disease", - "disk", - "energy", - "nation", - "road", - "role", - "soup", - "advertising", - "location", - "success", - "addition", - "apartment", - "education", - "math", - "moment", - "painting", - "politics", - "attention", - "decision", - "event", - "property", - "shopping", - "student", - "wood", - "competition", - "distribution", - "entertainment", - "office", - "population", - "president", - "unit", - "category", - "cigarette", - "context", - "introduction", - "opportunity", - "performance", - "driver", - "flight", - "length", - "magazine", - "newspaper", - "relationship", - "teaching", - "cell", - "dealer", - "finding", - "lake", - "member", - "message", - "phone", - "scene", - "appearance", - "association", - "concept", - "customer", - "death", - "discussion", - "housing", - "inflation", - "insurance", - "mood", - "woman", - "advice", - "blood", - "effort", - "expression", - "importance", - "opinion", - "payment", - "reality", - "responsibility", - "situation", - "skill", - "statement", - "wealth", - "application", - "city", - "county", - "depth", - "estate", - "foundation", - "grandmother", - "heart", - "perspective", - "photo", - "recipe", - "studio", - "topic", - "collection", - "depression", - "imagination", - "passion", - "percentage", - "resource", - "setting", - "ad", - "agency", - "college", - "connection", - "criticism", - "debt", - "description", - "memory", - "patience", - "secretary", - "solution", - "administration", - "aspect", - "attitude", - "director", - "personality", - "psychology", - "recommendation", - "response", - "selection", - "storage", - "version", - "alcohol", - "argument", - "complaint", - "contract", - "emphasis", - "highway", - "loss", - "membership", - "possession", - "preparation", - "steak", - "union", - "agreement", - "cancer", - "currency", - "employment", - "engineering", - "entry", - "interaction", - "mixture", - "preference", - "region", - "republic", - "tradition", - "virus", - "actor", - "classroom", - "delivery", - "device", - "difficulty", - "drama", - "election", - "engine", - "football", - "guidance", - "hotel", - "owner", - "priority", - "protection", - "suggestion", - "tension", - "variation", - "anxiety", - "atmosphere", - "awareness", - "bath", - "bread", - "candidate", - "climate", - "comparison", - "confusion", - "construction", - "elevator", - "emotion", - "employee", - "employer", - "guest", - "height", - "leadership", - "mall", - "manager", - "operation", - "recording", - "sample", - "transportation", - "charity", - "cousin", - "disaster", - "editor", - "efficiency", - "excitement", - "extent", - "feedback", - "guitar", - "homework", - "leader", - "mom", - "outcome", - "permission", - "presentation", - "promotion", - "reflection", - "refrigerator", - "resolution", - "revenue", - "session", - "singer", - "tennis", - "basket", - "bonus", - "cabinet", - "childhood", - "church", - "clothes", - "coffee", - "dinner", - "drawing", - "hair", - "hearing", - "initiative", - "judgment", - "lab", - "measurement", - "mode", - "mud", - "orange", - "poetry", - "police", - "possibility", - "procedure", - "queen", - "ratio", - "relation", - "restaurant", - "satisfaction", - "sector", - "signature", - "significance", - "song", - "tooth", - "town", - "vehicle", - "volume", - "wife", - "accident", - "airport", - "appointment", - "arrival", - "assumption", - "baseball", - "chapter", - "committee", - "conversation", - "database", - "enthusiasm", - "error", - "explanation", - "farmer", - "gate", - "girl", - "hall", - "historian", - "hospital", - "injury", - "instruction", - "maintenance", - "manufacturer", - "meal", - "perception", - "pie", - "poem", - "presence", - "proposal", - "reception", - "replacement", - "revolution", - "river", - "son", - "speech", - "tea", - "village", - "warning", - "winner", - "worker", - "writer", - "assistance", - "breath", - "buyer", - "chest", - "chocolate", - "conclusion", - "contribution", - "cookie", - "courage", - "dad", - "desk", - "drawer", - "establishment", - "examination", - "garbage", - "grocery", - "honey", - "impression", - "improvement", - "independence", - "insect", - "inspection", - "inspector", - "king", - "ladder", - "menu", - "penalty", - "piano", - "potato", - "profession", - "professor", - "quantity", - "reaction", - "requirement", - "salad", - "sister", - "supermarket", - "tongue", - "weakness", - "wedding", - "affair", - "ambition", - "analyst", - "apple", - "assignment", - "assistant", - "bathroom", - "bedroom", - "beer", - "birthday", - "celebration", - "championship", - "cheek", - "client", - "consequence", - "departure", - "diamond", - "dirt", - "ear", - "fortune", - "friendship", - "funeral", - "gene", - "girlfriend", - "hat", - "indication", - "intention", - "lady", - "midnight", - "negotiation", - "obligation", - "passenger", - "pizza", - "platform", - "poet", - "pollution", - "recognition", - "reputation", - "shirt", - "sir", - "speaker", - "stranger", - "surgery", - "sympathy", - "tale", - "throat", - "trainer", - "uncle", - "youth", - "time", - "work", - "film", - "water", - "money", - "example", - "while", - "business", - "study", - "game", - "life", - "form", - "air", - "day", - "place", - "number", - "part", - "field", - "fish", - "back", - "process", - "heat", - "hand", - "experience", - "job", - "book", - "end", - "point", - "type", - "home", - "economy", - "value", - "body", - "market", - "guide", - "interest", - "state", - "radio", - "course", - "company", - "price", - "size", - "card", - "list", - "mind", - "trade", - "line", - "care", - "group", - "risk", - "word", - "fat", - "force", - "key", - "light", - "training", - "name", - "school", - "top", - "amount", - "level", - "order", - "practice", - "research", - "sense", - "service", - "piece", - "web", - "boss", - "sport", - "fun", - "house", - "page", - "term", - "test", - "answer", - "sound", - "focus", - "matter", - "kind", - "soil", - "board", - "oil", - "picture", - "access", - "garden", - "range", - "rate", - "reason", - "future", - "site", - "demand", - "exercise", - "image", - "case", - "cause", - "coast", - "action", - "age", - "bad", - "boat", - "record", - "result", - "section", - "building", - "mouse", - "cash", - "class", - "nothing", - "period", - "plan", - "store", - "tax", - "side", - "subject", - "space", - "rule", - "stock", - "weather", - "chance", - "figure", - "man", - "model", - "source", - "beginning", - "earth", - "program", - "chicken", - "design", - "feature", - "head", - "material", - "purpose", - "question", - "rock", - "salt", - "act", - "birth", - "car", - "dog", - "object", - "scale", - "sun", - "note", - "profit", - "rent", - "speed", - "style", - "war", - "bank", - "craft", - "half", - "inside", - "outside", - "standard", - "bus", - "exchange", - "eye", - "fire", - "position", - "pressure", - "stress", - "advantage", - "benefit", - "box", - "frame", - "issue", - "step", - "cycle", - "face", - "item", - "metal", - "paint", - "review", - "room", - "screen", - "structure", - "view", - "account", - "ball", - "discipline", - "medium", - "share", - "balance", - "bit", - "black", - "bottom", - "choice", - "gift", - "impact", - "machine", - "shape", - "tool", - "wind", - "address", - "average", - "career", - "culture", - "morning", - "pot", - "sign", - "table", - "task", - "condition", - "contact", - "credit", - "egg", - "hope", - "ice", - "network", - "north", - "square", - "attempt", - "date", - "effect", - "link", - "post", - "star", - "voice", - "capital", - "challenge", - "friend", - "self", - "shot", - "brush", - "couple", - "debate", - "exit", - "front", - "function", - "lack", - "living", - "plant", - "plastic", - "spot", - "summer", - "taste", - "theme", - "track", - "wing", - "brain", - "button", - "click", - "desire", - "foot", - "gas", - "influence", - "notice", - "rain", - "wall", - "base", - "damage", - "distance", - "feeling", - "pair", - "savings", - "staff", - "sugar", - "target", - "text", - "animal", - "author", - "budget", - "discount", - "file", - "ground", - "lesson", - "minute", - "officer", - "phase", - "reference", - "register", - "sky", - "stage", - "stick", - "title", - "trouble", - "bowl", - "bridge", - "campaign", - "character", - "club", - "edge", - "evidence", - "fan", - "letter", - "lock", - "maximum", - "novel", - "option", - "pack", - "park", - "plenty", - "quarter", - "skin", - "sort", - "weight", - "baby", - "background", - "carry", - "dish", - "factor", - "fruit", - "glass", - "joint", - "master", - "muscle", - "red", - "strength", - "traffic", - "trip", - "vegetable", - "appeal", - "chart", - "gear", - "ideal", - "kitchen", - "land", - "log", - "mother", - "net", - "party", - "principle", - "relative", - "sale", - "season", - "signal", - "spirit", - "street", - "tree", - "wave", - "belt", - "bench", - "commission", - "copy", - "drop", - "minimum", - "path", - "progress", - "project", - "sea", - "south", - "status", - "stuff", - "ticket", - "tour", - "angle", - "blue", - "breakfast", - "confidence", - "daughter", - "degree", - "doctor", - "dot", - "dream", - "duty", - "essay", - "father", - "fee", - "finance", - "hour", - "juice", - "limit", - "luck", - "milk", - "mouth", - "peace", - "pipe", - "seat", - "stable", - "storm", - "substance", - "team", - "trick", - "afternoon", - "bat", - "beach", - "blank", - "catch", - "chain", - "consideration", - "cream", - "crew", - "detail", - "gold", - "interview", - "kid", - "mark", - "match", - "mission", - "pain", - "pleasure", - "score", - "screw", - "sex", - "shop", - "shower", - "suit", - "tone", - "window", - "agent", - "band", - "block", - "bone", - "calendar", - "cap", - "coat", - "contest", - "corner", - "court", - "cup", - "district", - "door", - "east", - "finger", - "garage", - "guarantee", - "hole", - "hook", - "implement", - "layer", - "lecture", - "lie", - "manner", - "meeting", - "nose", - "parking", - "partner", - "profile", - "respect", - "rice", - "routine", - "schedule", - "swimming", - "telephone", - "tip", - "winter", - "airline", - "bag", - "battle", - "bed", - "bill", - "bother", - "cake", - "code", - "curve", - "designer", - "dimension", - "dress", - "ease", - "emergency", - "evening", - "extension", - "farm", - "fight", - "gap", - "grade", - "holiday", - "horror", - "horse", - "host", - "husband", - "loan", - "mistake", - "mountain", - "nail", - "noise", - "occasion", - "package", - "patient", - "pause", - "phrase", - "proof", - "race", - "relief", - "sand", - "sentence", - "shoulder", - "smoke", - "stomach", - "string", - "tourist", - "towel", - "vacation", - "west", - "wheel", - "wine", - "arm", - "aside", - "associate", - "bet", - "blow", - "border", - "branch", - "breast", - "brother", - "buddy", - "bunch", - "chip", - "coach", - "cross", - "document", - "draft", - "dust", - "expert", - "floor", - "god", - "golf", - "habit", - "iron", - "judge", - "knife", - "landscape", - "league", - "mail", - "mess", - "native", - "opening", - "parent", - "pattern", - "pin", - "pool", - "pound", - "request", - "salary", - "shame", - "shelter", - "shoe", - "silver", - "tackle", - "tank", - "trust", - "assist", - "bake", - "bar", - "bell", - "bike", - "blame", - "boy", - "brick", - "chair", - "closet", - "clue", - "collar", - "comment", - "conference", - "devil", - "diet", - "fear", - "fuel", - "glove", - "jacket", - "lunch", - "monitor", - "mortgage", - "nurse", - "pace", - "panic", - "peak", - "plane", - "reward", - "row", - "sandwich", - "shock", - "spite", - "spray", - "surprise", - "till", - "transition", - "weekend", - "welcome", - "yard", - "alarm", - "bend", - "bicycle", - "bite", - "blind", - "bottle", - "cable", - "candle", - "clerk", - "cloud", - "concert", - "counter", - "flower", - "grandfather", - "harm", - "knee", - "lawyer", - "leather", - "load", - "mirror", - "neck", - "pension", - "plate", - "purple", - "ruin", - "ship", - "skirt", - "slice", - "snow", - "specialist", - "stroke", - "switch", - "trash", - "tune", - "zone", - "anger", - "award", - "bid", - "bitter", - "boot", - "bug", - "camp", - "candy", - "carpet", - "cat", - "champion", - "channel", - "clock", - "comfort", - "cow", - "crack", - "engineer", - "entrance", - "fault", - "grass", - "guy", - "hell", - "highlight", - "incident", - "island", - "joke", - "jury", - "leg", - "lip", - "mate", - "motor", - "nerve", - "passage", - "pen", - "pride", - "priest", - "prize", - "promise", - "resident", - "resort", - "ring", - "roof", - "rope", - "sail", - "scheme", - "script", - "sock", - "station", - "toe", - "tower", - "truck", - "witness", - "a", - "you", - "it", - "can", - "will", - "if", - "one", - "many", - "most", - "other", - "use", - "make", - "good", - "look", - "help", - "go", - "great", - "being", - "few", - "might", - "still", - "public", - "read", - "keep", - "start", - "give", - "human", - "local", - "general", - "she", - "specific", - "long", - "play", - "feel", - "high", - "tonight", - "put", - "common", - "set", - "change", - "simple", - "past", - "big", - "possible", - "particular", - "today", - "major", - "personal", - "current", - "national", - "cut", - "natural", - "physical", - "show", - "try", - "check", - "second", - "call", - "move", - "pay", - "let", - "increase", - "single", - "individual", - "turn", - "ask", - "buy", - "guard", - "hold", - "main", - "offer", - "potential", - "professional", - "international", - "travel", - "cook", - "alternative", - "following", - "special", - "working", - "whole", - "dance", - "excuse", - "cold", - "commercial", - "low", - "purchase", - "deal", - "primary", - "worth", - "fall", - "necessary", - "positive", - "produce", - "search", - "present", - "spend", - "talk", - "creative", - "tell", - "cost", - "drive", - "green", - "support", - "glad", - "remove", - "return", - "run", - "complex", - "due", - "effective", - "middle", - "regular", - "reserve", - "independent", - "leave", - "original", - "reach", - "rest", - "serve", - "watch", - "beautiful", - "charge", - "active", - "break", - "negative", - "safe", - "stay", - "visit", - "visual", - "affect", - "cover", - "report", - "rise", - "walk", - "white", - "beyond", - "junior", - "pick", - "unique", - "anything", - "classic", - "final", - "lift", - "mix", - "private", - "stop", - "teach", - "western", - "concern", - "familiar", - "fly", - "official", - "broad", - "comfortable", - "gain", - "maybe", - "rich", - "save", - "stand", - "young", - "fail", - "heavy", - "hello", - "lead", - "listen", - "valuable", - "worry", - "handle", - "leading", - "meet", - "release", - "sell", - "finish", - "normal", - "press", - "ride", - "secret", - "spread", - "spring", - "tough", - "wait", - "brown", - "deep", - "display", - "flow", - "hit", - "objective", - "shoot", - "touch", - "cancel", - "chemical", - "cry", - "dump", - "extreme", - "push", - "conflict", - "eat", - "fill", - "formal", - "jump", - "kick", - "opposite", - "pass", - "pitch", - "remote", - "total", - "treat", - "vast", - "abuse", - "beat", - "burn", - "deposit", - "print", - "raise", - "sleep", - "somewhere", - "advance", - "anywhere", - "consist", - "dark", - "double", - "draw", - "equal", - "fix", - "hire", - "internal", - "join", - "kill", - "sensitive", - "tap", - "win", - "attack", - "claim", - "constant", - "drag", - "drink", - "guess", - "minor", - "pull", - "raw", - "soft", - "solid", - "wear", - "weird", - "wonder", - "annual", - "count", - "dead", - "doubt", - "feed", - "forever", - "impress", - "nobody", - "repeat", - "round", - "sing", - "slide", - "strip", - "whereas", - "wish", - "combine", - "command", - "dig", - "divide", - "equivalent", - "hang", - "hunt", - "initial", - "march", - "mention", - "smell", - "spiritual", - "survey", - "tie", - "adult", - "brief", - "crazy", - "escape", - "gather", - "hate", - "prior", - "repair", - "rough", - "sad", - "scratch", - "sick", - "strike", - "employ", - "external", - "hurt", - "illegal", - "laugh", - "lay", - "mobile", - "nasty", - "ordinary", - "respond", - "royal", - "senior", - "split", - "strain", - "struggle", - "swim", - "train", - "upper", - "wash", - "yellow", - "convert", - "crash", - "dependent", - "fold", - "funny", - "grab", - "hide", - "miss", - "permit", - "quote", - "recover", - "resolve", - "roll", - "sink", - "slip", - "spare", - "suspect", - "sweet", - "swing", - "twist", - "upstairs", - "usual", - "abroad", - "brave", - "calm", - "concentrate", - "estimate", - "grand", - "male", - "mine", - "prompt", - "quiet", - "refuse", - "regret", - "reveal", - "rush", - "shake", - "shift", - "shine", - "steal", - "suck", - "surround", - "anybody", - "bear", - "brilliant", - "dare", - "dear", - "delay", - "drunk", - "female", - "hurry", - "inevitable", - "invite", - "kiss", - "neat", - "pop", - "punch", - "quit", - "reply", - "representative", - "resist", - "rip", - "rub", - "silly", - "smile", - "spell", - "stretch", - "stupid", - "tear", - "temporary", - "tomorrow", - "wake", - "wrap", - "yesterday" + "people", + "history", + "way", + "art", + "world", + "information", + "map", + "two", + "family", + "government", + "health", + "system", + "computer", + "meat", + "year", + "thanks", + "music", + "person", + "reading", + "method", + "data", + "food", + "understanding", + "theory", + "law", + "bird", + "literature", + "problem", + "software", + "control", + "knowledge", + "power", + "ability", + "economics", + "love", + "internet", + "television", + "science", + "library", + "nature", + "fact", + "product", + "idea", + "temperature", + "investment", + "area", + "society", + "activity", + "story", + "industry", + "media", + "thing", + "oven", + "community", + "definition", + "safety", + "quality", + "development", + "language", + "management", + "player", + "variety", + "video", + "week", + "security", + "country", + "exam", + "movie", + "organization", + "equipment", + "physics", + "analysis", + "policy", + "series", + "thought", + "basis", + "boyfriend", + "direction", + "strategy", + "technology", + "army", + "camera", + "freedom", + "paper", + "environment", + "child", + "instance", + "month", + "truth", + "marketing", + "university", + "writing", + "article", + "department", + "difference", + "goal", + "news", + "audience", + "fishing", + "growth", + "income", + "marriage", + "user", + "combination", + "failure", + "meaning", + "medicine", + "philosophy", + "teacher", + "communication", + "night", + "chemistry", + "disease", + "disk", + "energy", + "nation", + "road", + "role", + "soup", + "advertising", + "location", + "success", + "addition", + "apartment", + "education", + "math", + "moment", + "painting", + "politics", + "attention", + "decision", + "event", + "property", + "shopping", + "student", + "wood", + "competition", + "distribution", + "entertainment", + "office", + "population", + "president", + "unit", + "category", + "cigarette", + "context", + "introduction", + "opportunity", + "performance", + "driver", + "flight", + "length", + "magazine", + "newspaper", + "relationship", + "teaching", + "cell", + "dealer", + "finding", + "lake", + "member", + "message", + "phone", + "scene", + "appearance", + "association", + "concept", + "customer", + "death", + "discussion", + "housing", + "inflation", + "insurance", + "mood", + "woman", + "advice", + "blood", + "effort", + "expression", + "importance", + "opinion", + "payment", + "reality", + "responsibility", + "situation", + "skill", + "statement", + "wealth", + "application", + "city", + "county", + "depth", + "estate", + "foundation", + "grandmother", + "heart", + "perspective", + "photo", + "recipe", + "studio", + "topic", + "collection", + "depression", + "imagination", + "passion", + "percentage", + "resource", + "setting", + "ad", + "agency", + "college", + "connection", + "criticism", + "debt", + "description", + "memory", + "patience", + "secretary", + "solution", + "administration", + "aspect", + "attitude", + "director", + "personality", + "psychology", + "recommendation", + "response", + "selection", + "storage", + "version", + "alcohol", + "argument", + "complaint", + "contract", + "emphasis", + "highway", + "loss", + "membership", + "possession", + "preparation", + "steak", + "union", + "agreement", + "cancer", + "currency", + "employment", + "engineering", + "entry", + "interaction", + "mixture", + "preference", + "region", + "republic", + "tradition", + "virus", + "actor", + "classroom", + "delivery", + "device", + "difficulty", + "drama", + "election", + "engine", + "football", + "guidance", + "hotel", + "owner", + "priority", + "protection", + "suggestion", + "tension", + "variation", + "anxiety", + "atmosphere", + "awareness", + "bath", + "bread", + "candidate", + "climate", + "comparison", + "confusion", + "construction", + "elevator", + "emotion", + "employee", + "employer", + "guest", + "height", + "leadership", + "mall", + "manager", + "operation", + "recording", + "sample", + "transportation", + "charity", + "cousin", + "disaster", + "editor", + "efficiency", + "excitement", + "extent", + "feedback", + "guitar", + "homework", + "leader", + "mom", + "outcome", + "permission", + "presentation", + "promotion", + "reflection", + "refrigerator", + "resolution", + "revenue", + "session", + "singer", + "tennis", + "basket", + "bonus", + "cabinet", + "childhood", + "church", + "clothes", + "coffee", + "dinner", + "drawing", + "hair", + "hearing", + "initiative", + "judgment", + "lab", + "measurement", + "mode", + "mud", + "orange", + "poetry", + "police", + "possibility", + "procedure", + "queen", + "ratio", + "relation", + "restaurant", + "satisfaction", + "sector", + "signature", + "significance", + "song", + "tooth", + "town", + "vehicle", + "volume", + "wife", + "accident", + "airport", + "appointment", + "arrival", + "assumption", + "baseball", + "chapter", + "committee", + "conversation", + "database", + "enthusiasm", + "error", + "explanation", + "farmer", + "gate", + "girl", + "hall", + "historian", + "hospital", + "injury", + "instruction", + "maintenance", + "manufacturer", + "meal", + "perception", + "pie", + "poem", + "presence", + "proposal", + "reception", + "replacement", + "revolution", + "river", + "son", + "speech", + "tea", + "village", + "warning", + "winner", + "worker", + "writer", + "assistance", + "breath", + "buyer", + "chest", + "chocolate", + "conclusion", + "contribution", + "cookie", + "courage", + "dad", + "desk", + "drawer", + "establishment", + "examination", + "garbage", + "grocery", + "honey", + "impression", + "improvement", + "independence", + "insect", + "inspection", + "inspector", + "king", + "ladder", + "menu", + "penalty", + "piano", + "potato", + "profession", + "professor", + "quantity", + "reaction", + "requirement", + "salad", + "sister", + "supermarket", + "tongue", + "weakness", + "wedding", + "affair", + "ambition", + "analyst", + "apple", + "assignment", + "assistant", + "bathroom", + "bedroom", + "beer", + "birthday", + "celebration", + "championship", + "cheek", + "client", + "consequence", + "departure", + "diamond", + "dirt", + "ear", + "fortune", + "friendship", + "funeral", + "gene", + "girlfriend", + "hat", + "indication", + "intention", + "lady", + "midnight", + "negotiation", + "obligation", + "passenger", + "pizza", + "platform", + "poet", + "pollution", + "recognition", + "reputation", + "shirt", + "sir", + "speaker", + "stranger", + "surgery", + "sympathy", + "tale", + "throat", + "trainer", + "uncle", + "youth", + "time", + "work", + "film", + "water", + "money", + "example", + "while", + "business", + "study", + "game", + "life", + "form", + "air", + "day", + "place", + "number", + "part", + "field", + "fish", + "back", + "process", + "heat", + "hand", + "experience", + "job", + "book", + "end", + "point", + "type", + "home", + "economy", + "value", + "body", + "market", + "guide", + "interest", + "state", + "radio", + "course", + "company", + "price", + "size", + "card", + "list", + "mind", + "trade", + "line", + "care", + "group", + "risk", + "word", + "fat", + "force", + "key", + "light", + "training", + "name", + "school", + "top", + "amount", + "level", + "order", + "practice", + "research", + "sense", + "service", + "piece", + "web", + "boss", + "sport", + "fun", + "house", + "page", + "term", + "test", + "answer", + "sound", + "focus", + "matter", + "kind", + "soil", + "board", + "oil", + "picture", + "access", + "garden", + "range", + "rate", + "reason", + "future", + "site", + "demand", + "exercise", + "image", + "case", + "cause", + "coast", + "action", + "age", + "bad", + "boat", + "record", + "result", + "section", + "building", + "mouse", + "cash", + "class", + "nothing", + "period", + "plan", + "store", + "tax", + "side", + "subject", + "space", + "rule", + "stock", + "weather", + "chance", + "figure", + "man", + "model", + "source", + "beginning", + "earth", + "program", + "chicken", + "design", + "feature", + "head", + "material", + "purpose", + "question", + "rock", + "salt", + "act", + "birth", + "car", + "dog", + "object", + "scale", + "sun", + "note", + "profit", + "rent", + "speed", + "style", + "war", + "bank", + "craft", + "half", + "inside", + "outside", + "standard", + "bus", + "exchange", + "eye", + "fire", + "position", + "pressure", + "stress", + "advantage", + "benefit", + "box", + "frame", + "issue", + "step", + "cycle", + "face", + "item", + "metal", + "paint", + "review", + "room", + "screen", + "structure", + "view", + "account", + "ball", + "discipline", + "medium", + "share", + "balance", + "bit", + "black", + "bottom", + "choice", + "gift", + "impact", + "machine", + "shape", + "tool", + "wind", + "address", + "average", + "career", + "culture", + "morning", + "pot", + "sign", + "table", + "task", + "condition", + "contact", + "credit", + "egg", + "hope", + "ice", + "network", + "north", + "square", + "attempt", + "date", + "effect", + "link", + "post", + "star", + "voice", + "capital", + "challenge", + "friend", + "self", + "shot", + "brush", + "couple", + "debate", + "exit", + "front", + "function", + "lack", + "living", + "plant", + "plastic", + "spot", + "summer", + "taste", + "theme", + "track", + "wing", + "brain", + "button", + "click", + "desire", + "foot", + "gas", + "influence", + "notice", + "rain", + "wall", + "base", + "damage", + "distance", + "feeling", + "pair", + "savings", + "staff", + "sugar", + "target", + "text", + "animal", + "author", + "budget", + "discount", + "file", + "ground", + "lesson", + "minute", + "officer", + "phase", + "reference", + "register", + "sky", + "stage", + "stick", + "title", + "trouble", + "bowl", + "bridge", + "campaign", + "character", + "club", + "edge", + "evidence", + "fan", + "letter", + "lock", + "maximum", + "novel", + "option", + "pack", + "park", + "plenty", + "quarter", + "skin", + "sort", + "weight", + "baby", + "background", + "carry", + "dish", + "factor", + "fruit", + "glass", + "joint", + "master", + "muscle", + "red", + "strength", + "traffic", + "trip", + "vegetable", + "appeal", + "chart", + "gear", + "ideal", + "kitchen", + "land", + "log", + "mother", + "net", + "party", + "principle", + "relative", + "sale", + "season", + "signal", + "spirit", + "street", + "tree", + "wave", + "belt", + "bench", + "commission", + "copy", + "drop", + "minimum", + "path", + "progress", + "project", + "sea", + "south", + "status", + "stuff", + "ticket", + "tour", + "angle", + "blue", + "breakfast", + "confidence", + "daughter", + "degree", + "doctor", + "dot", + "dream", + "duty", + "essay", + "father", + "fee", + "finance", + "hour", + "juice", + "limit", + "luck", + "milk", + "mouth", + "peace", + "pipe", + "seat", + "stable", + "storm", + "substance", + "team", + "trick", + "afternoon", + "bat", + "beach", + "blank", + "catch", + "chain", + "consideration", + "cream", + "crew", + "detail", + "gold", + "interview", + "kid", + "mark", + "match", + "mission", + "pain", + "pleasure", + "score", + "screw", + "sex", + "shop", + "shower", + "suit", + "tone", + "window", + "agent", + "band", + "block", + "bone", + "calendar", + "cap", + "coat", + "contest", + "corner", + "court", + "cup", + "district", + "door", + "east", + "finger", + "garage", + "guarantee", + "hole", + "hook", + "implement", + "layer", + "lecture", + "lie", + "manner", + "meeting", + "nose", + "parking", + "partner", + "profile", + "respect", + "rice", + "routine", + "schedule", + "swimming", + "telephone", + "tip", + "winter", + "airline", + "bag", + "battle", + "bed", + "bill", + "bother", + "cake", + "code", + "curve", + "designer", + "dimension", + "dress", + "ease", + "emergency", + "evening", + "extension", + "farm", + "fight", + "gap", + "grade", + "holiday", + "horror", + "horse", + "host", + "husband", + "loan", + "mistake", + "mountain", + "nail", + "noise", + "occasion", + "package", + "patient", + "pause", + "phrase", + "proof", + "race", + "relief", + "sand", + "sentence", + "shoulder", + "smoke", + "stomach", + "string", + "tourist", + "towel", + "vacation", + "west", + "wheel", + "wine", + "arm", + "aside", + "associate", + "bet", + "blow", + "border", + "branch", + "breast", + "brother", + "buddy", + "bunch", + "chip", + "coach", + "cross", + "document", + "draft", + "dust", + "expert", + "floor", + "god", + "golf", + "habit", + "iron", + "judge", + "knife", + "landscape", + "league", + "mail", + "mess", + "native", + "opening", + "parent", + "pattern", + "pin", + "pool", + "pound", + "request", + "salary", + "shame", + "shelter", + "shoe", + "silver", + "tackle", + "tank", + "trust", + "assist", + "bake", + "bar", + "bell", + "bike", + "blame", + "boy", + "brick", + "chair", + "closet", + "clue", + "collar", + "comment", + "conference", + "devil", + "diet", + "fear", + "fuel", + "glove", + "jacket", + "lunch", + "monitor", + "mortgage", + "nurse", + "pace", + "panic", + "peak", + "plane", + "reward", + "row", + "sandwich", + "shock", + "spite", + "spray", + "surprise", + "till", + "transition", + "weekend", + "welcome", + "yard", + "alarm", + "bend", + "bicycle", + "bite", + "blind", + "bottle", + "cable", + "candle", + "clerk", + "cloud", + "concert", + "counter", + "flower", + "grandfather", + "harm", + "knee", + "lawyer", + "leather", + "load", + "mirror", + "neck", + "pension", + "plate", + "purple", + "ruin", + "ship", + "skirt", + "slice", + "snow", + "specialist", + "stroke", + "switch", + "trash", + "tune", + "zone", + "anger", + "award", + "bid", + "bitter", + "boot", + "bug", + "camp", + "candy", + "carpet", + "cat", + "champion", + "channel", + "clock", + "comfort", + "cow", + "crack", + "engineer", + "entrance", + "fault", + "grass", + "guy", + "hell", + "highlight", + "incident", + "island", + "joke", + "jury", + "leg", + "lip", + "mate", + "motor", + "nerve", + "passage", + "pen", + "pride", + "priest", + "prize", + "promise", + "resident", + "resort", + "ring", + "roof", + "rope", + "sail", + "scheme", + "script", + "sock", + "station", + "toe", + "tower", + "truck", + "witness", + "a", + "you", + "it", + "can", + "will", + "if", + "one", + "many", + "most", + "other", + "use", + "make", + "good", + "look", + "help", + "go", + "great", + "being", + "few", + "might", + "still", + "public", + "read", + "keep", + "start", + "give", + "human", + "local", + "general", + "she", + "specific", + "long", + "play", + "feel", + "high", + "tonight", + "put", + "common", + "set", + "change", + "simple", + "past", + "big", + "possible", + "particular", + "today", + "major", + "personal", + "current", + "national", + "cut", + "natural", + "physical", + "show", + "try", + "check", + "second", + "call", + "move", + "pay", + "let", + "increase", + "single", + "individual", + "turn", + "ask", + "buy", + "guard", + "hold", + "main", + "offer", + "potential", + "professional", + "international", + "travel", + "cook", + "alternative", + "following", + "special", + "working", + "whole", + "dance", + "excuse", + "cold", + "commercial", + "low", + "purchase", + "deal", + "primary", + "worth", + "fall", + "necessary", + "positive", + "produce", + "search", + "present", + "spend", + "talk", + "creative", + "tell", + "cost", + "drive", + "green", + "support", + "glad", + "remove", + "return", + "run", + "complex", + "due", + "effective", + "middle", + "regular", + "reserve", + "independent", + "leave", + "original", + "reach", + "rest", + "serve", + "watch", + "beautiful", + "charge", + "active", + "break", + "negative", + "safe", + "stay", + "visit", + "visual", + "affect", + "cover", + "report", + "rise", + "walk", + "white", + "beyond", + "junior", + "pick", + "unique", + "anything", + "classic", + "final", + "lift", + "mix", + "private", + "stop", + "teach", + "western", + "concern", + "familiar", + "fly", + "official", + "broad", + "comfortable", + "gain", + "maybe", + "rich", + "save", + "stand", + "young", + "fail", + "heavy", + "hello", + "lead", + "listen", + "valuable", + "worry", + "handle", + "leading", + "meet", + "release", + "sell", + "finish", + "normal", + "press", + "ride", + "secret", + "spread", + "spring", + "tough", + "wait", + "brown", + "deep", + "display", + "flow", + "hit", + "objective", + "shoot", + "touch", + "cancel", + "chemical", + "cry", + "dump", + "extreme", + "push", + "conflict", + "eat", + "fill", + "formal", + "jump", + "kick", + "opposite", + "pass", + "pitch", + "remote", + "total", + "treat", + "vast", + "abuse", + "beat", + "burn", + "deposit", + "print", + "raise", + "sleep", + "somewhere", + "advance", + "anywhere", + "consist", + "dark", + "double", + "draw", + "equal", + "fix", + "hire", + "internal", + "join", + "kill", + "sensitive", + "tap", + "win", + "attack", + "claim", + "constant", + "drag", + "drink", + "guess", + "minor", + "pull", + "raw", + "soft", + "solid", + "wear", + "weird", + "wonder", + "annual", + "count", + "dead", + "doubt", + "feed", + "forever", + "impress", + "nobody", + "repeat", + "round", + "sing", + "slide", + "strip", + "whereas", + "wish", + "combine", + "command", + "dig", + "divide", + "equivalent", + "hang", + "hunt", + "initial", + "march", + "mention", + "smell", + "spiritual", + "survey", + "tie", + "adult", + "brief", + "crazy", + "escape", + "gather", + "hate", + "prior", + "repair", + "rough", + "sad", + "scratch", + "sick", + "strike", + "employ", + "external", + "hurt", + "illegal", + "laugh", + "lay", + "mobile", + "nasty", + "ordinary", + "respond", + "royal", + "senior", + "split", + "strain", + "struggle", + "swim", + "train", + "upper", + "wash", + "yellow", + "convert", + "crash", + "dependent", + "fold", + "funny", + "grab", + "hide", + "miss", + "permit", + "quote", + "recover", + "resolve", + "roll", + "sink", + "slip", + "spare", + "suspect", + "sweet", + "swing", + "twist", + "upstairs", + "usual", + "abroad", + "brave", + "calm", + "concentrate", + "estimate", + "grand", + "male", + "mine", + "prompt", + "quiet", + "refuse", + "regret", + "reveal", + "rush", + "shake", + "shift", + "shine", + "steal", + "suck", + "surround", + "anybody", + "bear", + "brilliant", + "dare", + "dear", + "delay", + "drunk", + "female", + "hurry", + "inevitable", + "invite", + "kiss", + "neat", + "pop", + "punch", + "quit", + "reply", + "representative", + "resist", + "rip", + "rub", + "silly", + "smile", + "spell", + "stretch", + "stupid", + "tear", + "temporary", + "tomorrow", + "wake", + "wrap", + "yesterday" ] const adj = [ - "abandoned", - "able", - "absolute", - "adorable", - "adventurous", - "academic", - "acceptable", - "acclaimed", - "accomplished", - "accurate", - "aching", - "acidic", - "acrobatic", - "active", - "actual", - "adept", - "admirable", - "admired", - "adolescent", - "adorable", - "adored", - "advanced", - "afraid", - "affectionate", - "aged", - "aggravating", - "aggressive", - "agile", - "agitated", - "agonizing", - "agreeable", - "ajar", - "alarmed", - "alarming", - "alert", - "alienated", - "alive", - "all", - "altruistic", - "amazing", - "ambitious", - "ample", - "amused", - "amusing", - "anchored", - "ancient", - "angelic", - "angry", - "anguished", - "animated", - "annual", - "another", - "antique", - "anxious", - "any", - "apprehensive", - "appropriate", - "apt", - "arctic", - "arid", - "aromatic", - "artistic", - "ashamed", - "assured", - "astonishing", - "athletic", - "attached", - "attentive", - "attractive", - "austere", - "authentic", - "authorized", - "automatic", - "avaricious", - "average", - "aware", - "awesome", - "awful", - "awkward", - "babyish", - "bad", - "back", - "baggy", - "bare", - "barren", - "basic", - "beautiful", - "belated", - "beloved", - "beneficial", - "better", - "best", - "bewitched", - "big", - "big-hearted", - "biodegradable", - "bite-sized", - "bitter", - "black", - "black-and-white", - "bland", - "blank", - "blaring", - "bleak", - "blind", - "blissful", - "blond", - "blue", - "blushing", - "bogus", - "boiling", - "bold", - "bony", - "boring", - "bossy", - "both", - "bouncy", - "bountiful", - "bowed", - "brave", - "breakable", - "brief", - "bright", - "brilliant", - "brisk", - "broken", - "bronze", - "brown", - "bruised", - "bubbly", - "bulky", - "bumpy", - "buoyant", - "burdensome", - "burly", - "bustling", - "busy", - "buttery", - "buzzing", - "calculating", - "calm", - "candid", - "canine", - "capital", - "carefree", - "careful", - "careless", - "caring", - "cautious", - "cavernous", - "celebrated", - "charming", - "cheap", - "cheerful", - "cheery", - "chief", - "chilly", - "chubby", - "circular", - "classic", - "clean", - "clear", - "clear-cut", - "clever", - "close", - "closed", - "cloudy", - "clueless", - "clumsy", - "cluttered", - "coarse", - "cold", - "colorful", - "colorless", - "colossal", - "comfortable", - "common", - "compassionate", - "competent", - "complete", - "complex", - "complicated", - "composed", - "concerned", - "concrete", - "confused", - "conscious", - "considerate", - "constant", - "content", - "conventional", - "cooked", - "cool", - "cooperative", - "coordinated", - "corny", - "corrupt", - "costly", - "courageous", - "courteous", - "crafty", - "crazy", - "creamy", - "creative", - "creepy", - "criminal", - "crisp", - "critical", - "crooked", - "crowded", - "cruel", - "crushing", - "cuddly", - "cultivated", - "cultured", - "cumbersome", - "curly", - "curvy", - "cute", - "cylindrical", - "damaged", - "damp", - "dangerous", - "dapper", - "daring", - "darling", - "dark", - "dazzling", - "dead", - "deadly", - "deafening", - "dear", - "dearest", - "decent", - "decimal", - "decisive", - "deep", - "defenseless", - "defensive", - "defiant", - "deficient", - "definite", - "definitive", - "delayed", - "delectable", - "delicious", - "delightful", - "delirious", - "demanding", - "dense", - "dental", - "dependable", - "dependent", - "descriptive", - "deserted", - "detailed", - "determined", - "devoted", - "different", - "difficult", - "digital", - "diligent", - "dim", - "dimpled", - "dimwitted", - "direct", - "disastrous", - "discrete", - "disfigured", - "disgusting", - "disloyal", - "dismal", - "distant", - "downright", - "dreary", - "dirty", - "disguised", - "dishonest", - "dismal", - "distant", - "distinct", - "distorted", - "dizzy", - "dopey", - "doting", - "double", - "downright", - "drab", - "drafty", - "dramatic", - "dreary", - "droopy", - "dry", - "dual", - "dull", - "dutiful", - "each", - "eager", - "earnest", - "early", - "easy", - "easy-going", - "ecstatic", - "edible", - "educated", - "elaborate", - "elastic", - "elated", - "elderly", - "electric", - "elegant", - "elementary", - "elliptical", - "embarrassed", - "embellished", - "eminent", - "emotional", - "empty", - "enchanted", - "enchanting", - "energetic", - "enlightened", - "enormous", - "enraged", - "entire", - "envious", - "equal", - "equatorial", - "essential", - "esteemed", - "ethical", - "euphoric", - "even", - "evergreen", - "everlasting", - "every", - "evil", - "exalted", - "excellent", - "exemplary", - "exhausted", - "excitable", - "excited", - "exciting", - "exotic", - "expensive", - "experienced", - "expert", - "extraneous", - "extroverted", - "extra-large", - "extra-small", - "fabulous", - "failing", - "faint", - "fair", - "faithful", - "fake", - "false", - "familiar", - "famous", - "fancy", - "fantastic", - "far", - "faraway", - "far-flung", - "far-off", - "fast", - "fat", - "fatal", - "fatherly", - "favorable", - "favorite", - "fearful", - "fearless", - "feisty", - "feline", - "female", - "feminine", - "few", - "fickle", - "filthy", - "fine", - "finished", - "firm", - "first", - "firsthand", - "fitting", - "fixed", - "flaky", - "flamboyant", - "flashy", - "flat", - "flawed", - "flawless", - "flickering", - "flimsy", - "flippant", - "flowery", - "fluffy", - "fluid", - "flustered", - "focused", - "fond", - "foolhardy", - "foolish", - "forceful", - "forked", - "formal", - "forsaken", - "forthright", - "fortunate", - "fragrant", - "frail", - "frank", - "frayed", - "free", - "French", - "fresh", - "frequent", - "friendly", - "frightened", - "frightening", - "frigid", - "frilly", - "frizzy", - "frivolous", - "front", - "frosty", - "frozen", - "frugal", - "fruitful", - "full", - "fumbling", - "functional", - "funny", - "fussy", - "fuzzy", - "gargantuan", - "gaseous", - "general", - "generous", - "gentle", - "genuine", - "giant", - "giddy", - "gigantic", - "gifted", - "giving", - "glamorous", - "glaring", - "glass", - "gleaming", - "gleeful", - "glistening", - "glittering", - "gloomy", - "glorious", - "glossy", - "glum", - "golden", - "good", - "good-natured", - "gorgeous", - "graceful", - "gracious", - "grand", - "grandiose", - "granular", - "grateful", - "grave", - "gray", - "great", - "greedy", - "green", - "gregarious", - "grim", - "grimy", - "gripping", - "grizzled", - "gross", - "grotesque", - "grouchy", - "grounded", - "growing", - "growling", - "grown", - "grubby", - "gruesome", - "grumpy", - "guilty", - "gullible", - "gummy", - "hairy", - "half", - "handmade", - "handsome", - "handy", - "happy", - "happy-go-lucky", - "hard", - "hard-to-find", - "harmful", - "harmless", - "harmonious", - "harsh", - "hasty", - "hateful", - "haunting", - "healthy", - "heartfelt", - "hearty", - "heavenly", - "heavy", - "hefty", - "helpful", - "helpless", - "hidden", - "hideous", - "high", - "high-level", - "hilarious", - "hoarse", - "hollow", - "homely", - "honest", - "honorable", - "honored", - "hopeful", - "horrible", - "hospitable", - "hot", - "huge", - "humble", - "humiliating", - "humming", - "humongous", - "hungry", - "hurtful", - "husky", - "icky", - "icy", - "ideal", - "idealistic", - "identical", - "idle", - "idiotic", - "idolized", - "ignorant", - "ill", - "illegal", - "ill-fated", - "ill-informed", - "illiterate", - "illustrious", - "imaginary", - "imaginative", - "immaculate", - "immaterial", - "immediate", - "immense", - "impassioned", - "impeccable", - "impartial", - "imperfect", - "imperturbable", - "impish", - "impolite", - "important", - "impossible", - "impractical", - "impressionable", - "impressive", - "improbable", - "impure", - "inborn", - "incomparable", - "incompatible", - "incomplete", - "inconsequential", - "incredible", - "indelible", - "inexperienced", - "indolent", - "infamous", - "infantile", - "infatuated", - "inferior", - "infinite", - "informal", - "innocent", - "insecure", - "insidious", - "insignificant", - "insistent", - "instructive", - "insubstantial", - "intelligent", - "intent", - "intentional", - "interesting", - "internal", - "international", - "intrepid", - "ironclad", - "irresponsible", - "irritating", - "itchy", - "jaded", - "jagged", - "jam-packed", - "jaunty", - "jealous", - "jittery", - "joint", - "jolly", - "jovial", - "joyful", - "joyous", - "jubilant", - "judicious", - "juicy", - "jumbo", - "junior", - "jumpy", - "juvenile", - "kaleidoscopic", - "keen", - "key", - "kind", - "kindhearted", - "kindly", - "klutzy", - "knobby", - "knotty", - "knowledgeable", - "knowing", - "known", - "kooky", - "kosher", - "lame", - "lanky", - "large", - "last", - "lasting", - "late", - "lavish", - "lawful", - "lazy", - "leading", - "lean", - "leafy", - "left", - "legal", - "legitimate", - "light", - "lighthearted", - "likable", - "likely", - "limited", - "limp", - "limping", - "linear", - "lined", - "liquid", - "little", - "live", - "lively", - "livid", - "loathsome", - "lone", - "lonely", - "long", - "long-term", - "loose", - "lopsided", - "lost", - "loud", - "lovable", - "lovely", - "loving", - "low", - "loyal", - "lucky", - "lumbering", - "luminous", - "lumpy", - "lustrous", - "luxurious", - "mad", - "made-up", - "magnificent", - "majestic", - "major", - "male", - "mammoth", - "married", - "marvelous", - "masculine", - "massive", - "mature", - "meager", - "mealy", - "mean", - "measly", - "meaty", - "medical", - "mediocre", - "medium", - "meek", - "mellow", - "melodic", - "memorable", - "menacing", - "merry", - "messy", - "metallic", - "mild", - "milky", - "mindless", - "miniature", - "minor", - "minty", - "miserable", - "miserly", - "misguided", - "misty", - "mixed", - "modern", - "modest", - "moist", - "monstrous", - "monthly", - "monumental", - "moral", - "mortified", - "motherly", - "motionless", - "mountainous", - "muddy", - "muffled", - "multicolored", - "mundane", - "murky", - "mushy", - "musty", - "muted", - "mysterious", - "naive", - "narrow", - "nasty", - "natural", - "naughty", - "nautical", - "near", - "neat", - "necessary", - "needy", - "negative", - "neglected", - "negligible", - "neighboring", - "nervous", - "new", - "next", - "nice", - "nifty", - "nimble", - "nippy", - "nocturnal", - "noisy", - "nonstop", - "normal", - "notable", - "noted", - "noteworthy", - "novel", - "noxious", - "numb", - "nutritious", - "nutty", - "obedient", - "obese", - "oblong", - "oily", - "oblong", - "obvious", - "occasional", - "odd", - "oddball", - "offbeat", - "offensive", - "official", - "old", - "old-fashioned", - "only", - "open", - "optimal", - "optimistic", - "opulent", - "orange", - "orderly", - "organic", - "ornate", - "ornery", - "ordinary", - "original", - "other", - "our", - "outlying", - "outgoing", - "outlandish", - "outrageous", - "outstanding", - "oval", - "overcooked", - "overdue", - "overjoyed", - "overlooked", - "palatable", - "pale", - "paltry", - "parallel", - "parched", - "partial", - "passionate", - "past", - "pastel", - "peaceful", - "peppery", - "perfect", - "perfumed", - "periodic", - "perky", - "personal", - "pertinent", - "pesky", - "pessimistic", - "petty", - "phony", - "physical", - "piercing", - "pink", - "pitiful", - "plain", - "plaintive", - "plastic", - "playful", - "pleasant", - "pleased", - "pleasing", - "plump", - "plush", - "polished", - "polite", - "political", - "pointed", - "pointless", - "poised", - "poor", - "popular", - "portly", - "posh", - "positive", - "possible", - "potable", - "powerful", - "powerless", - "practical", - "precious", - "present", - "prestigious", - "pretty", - "precious", - "previous", - "pricey", - "prickly", - "primary", - "prime", - "pristine", - "private", - "prize", - "probable", - "productive", - "profitable", - "profuse", - "proper", - "proud", - "prudent", - "punctual", - "pungent", - "puny", - "pure", - "purple", - "pushy", - "putrid", - "puzzled", - "puzzling", - "quaint", - "qualified", - "quarrelsome", - "quarterly", - "queasy", - "querulous", - "questionable", - "quick", - "quick-witted", - "quiet", - "quintessential", - "quirky", - "quixotic", - "quizzical", - "radiant", - "ragged", - "rapid", - "rare", - "rash", - "raw", - "recent", - "reckless", - "rectangular", - "ready", - "real", - "realistic", - "reasonable", - "red", - "reflecting", - "regal", - "regular", - "reliable", - "relieved", - "remarkable", - "remorseful", - "remote", - "repentant", - "required", - "respectful", - "responsible", - "repulsive", - "revolving", - "rewarding", - "rich", - "rigid", - "right", - "ringed", - "ripe", - "roasted", - "robust", - "rosy", - "rotating", - "rotten", - "rough", - "round", - "rowdy", - "royal", - "rubbery", - "rundown", - "ruddy", - "rude", - "runny", - "rural", - "rusty", - "sad", - "safe", - "salty", - "same", - "sandy", - "sane", - "sarcastic", - "sardonic", - "satisfied", - "scaly", - "scarce", - "scared", - "scary", - "scented", - "scholarly", - "scientific", - "scornful", - "scratchy", - "scrawny", - "second", - "secondary", - "second-hand", - "secret", - "self-assured", - "self-reliant", - "selfish", - "sentimental", - "separate", - "serene", - "serious", - "serpentine", - "several", - "severe", - "shabby", - "shadowy", - "shady", - "shallow", - "shameful", - "shameless", - "sharp", - "shimmering", - "shiny", - "shocked", - "shocking", - "shoddy", - "short", - "short-term", - "showy", - "shrill", - "shy", - "sick", - "silent", - "silky", - "silly", - "silver", - "similar", - "simple", - "simplistic", - "sinful", - "single", - "sizzling", - "skeletal", - "skinny", - "sleepy", - "slight", - "slim", - "slimy", - "slippery", - "slow", - "slushy", - "small", - "smart", - "smoggy", - "smooth", - "smug", - "snappy", - "snarling", - "sneaky", - "sniveling", - "snoopy", - "sociable", - "soft", - "soggy", - "solid", - "somber", - "some", - "spherical", - "sophisticated", - "sore", - "sorrowful", - "soulful", - "soupy", - "sour", - "Spanish", - "sparkling", - "sparse", - "specific", - "spectacular", - "speedy", - "spicy", - "spiffy", - "spirited", - "spiteful", - "splendid", - "spotless", - "spotted", - "spry", - "square", - "squeaky", - "squiggly", - "stable", - "staid", - "stained", - "stale", - "standard", - "starchy", - "stark", - "starry", - "steep", - "sticky", - "stiff", - "stimulating", - "stingy", - "stormy", - "straight", - "strange", - "steel", - "strict", - "strident", - "striking", - "striped", - "strong", - "studious", - "stunning", - "stupendous", - "stupid", - "sturdy", - "stylish", - "subdued", - "submissive", - "substantial", - "subtle", - "suburban", - "sudden", - "sugary", - "sunny", - "super", - "superb", - "superficial", - "superior", - "supportive", - "sure-footed", - "surprised", - "suspicious", - "svelte", - "sweaty", - "sweet", - "sweltering", - "swift", - "sympathetic", - "tall", - "talkative", - "tame", - "tan", - "tangible", - "tart", - "tasty", - "tattered", - "taut", - "tedious", - "teeming", - "tempting", - "tender", - "tense", - "tepid", - "terrible", - "terrific", - "testy", - "thankful", - "that", - "these", - "thick", - "thin", - "third", - "thirsty", - "this", - "thorough", - "thorny", - "those", - "thoughtful", - "threadbare", - "thrifty", - "thunderous", - "tidy", - "tight", - "timely", - "tinted", - "tiny", - "tired", - "torn", - "total", - "tough", - "traumatic", - "treasured", - "tremendous", - "tragic", - "trained", - "tremendous", - "triangular", - "tricky", - "trifling", - "trim", - "trivial", - "troubled", - "true", - "trusting", - "trustworthy", - "trusty", - "truthful", - "tubby", - "turbulent", - "twin", - "ugly", - "ultimate", - "unacceptable", - "unaware", - "uncomfortable", - "uncommon", - "unconscious", - "understated", - "unequaled", - "uneven", - "unfinished", - "unfit", - "unfolded", - "unfortunate", - "unhappy", - "unhealthy", - "uniform", - "unimportant", - "unique", - "united", - "unkempt", - "unknown", - "unlawful", - "unlined", - "unlucky", - "unnatural", - "unpleasant", - "unrealistic", - "unripe", - "unruly", - "unselfish", - "unsightly", - "unsteady", - "unsung", - "untidy", - "untimely", - "untried", - "untrue", - "unused", - "unusual", - "unwelcome", - "unwieldy", - "unwilling", - "unwitting", - "unwritten", - "upbeat", - "upright", - "upset", - "urban", - "usable", - "used", - "useful", - "useless", - "utilized", - "utter", - "vacant", - "vague", - "vain", - "valid", - "valuable", - "vapid", - "variable", - "vast", - "velvety", - "venerated", - "vengeful", - "verifiable", - "vibrant", - "vicious", - "victorious", - "vigilant", - "vigorous", - "villainous", - "violet", - "violent", - "virtual", - "virtuous", - "visible", - "vital", - "vivacious", - "vivid", - "voluminous", - "wan", - "warlike", - "warm", - "warmhearted", - "warped", - "wary", - "wasteful", - "watchful", - "waterlogged", - "watery", - "wavy", - "wealthy", - "weak", - "weary", - "webbed", - "wee", - "weekly", - "weepy", - "weighty", - "weird", - "welcome", - "well-documented", - "well-groomed", - "well-informed", - "well-lit", - "well-made", - "well-off", - "well-to-do", - "well-worn", - "wet", - "which", - "whimsical", - "whirlwind", - "whispered", - "white", - "whole", - "whopping", - "wicked", - "wide", - "wide-eyed", - "wiggly", - "wild", - "willing", - "wilted", - "winding", - "windy", - "winged", - "wiry", - "wise", - "witty", - "wobbly", - "woeful", - "wonderful", - "wooden", - "woozy", - "wordy", - "worldly", - "worn", - "worried", - "worrisome", - "worse", - "worst", - "worthless", - "worthwhile", - "worthy", - "wrathful", - "wretched", - "writhing", - "wrong", - "wry", - "yawning", - "yearly", - "yellow", - "yellowish", - "young", - "youthful", - "yummy", - "zany", - "zealous", - "zesty", - "zigzag", + "abandoned", + "able", + "absolute", + "adorable", + "adventurous", + "academic", + "acceptable", + "acclaimed", + "accomplished", + "accurate", + "aching", + "acidic", + "acrobatic", + "active", + "actual", + "adept", + "admirable", + "admired", + "adolescent", + "adorable", + "adored", + "advanced", + "afraid", + "affectionate", + "aged", + "aggravating", + "aggressive", + "agile", + "agitated", + "agonizing", + "agreeable", + "ajar", + "alarmed", + "alarming", + "alert", + "alienated", + "alive", + "all", + "altruistic", + "amazing", + "ambitious", + "ample", + "amused", + "amusing", + "anchored", + "ancient", + "angelic", + "angry", + "anguished", + "animated", + "annual", + "another", + "antique", + "anxious", + "any", + "apprehensive", + "appropriate", + "apt", + "arctic", + "arid", + "aromatic", + "artistic", + "ashamed", + "assured", + "astonishing", + "athletic", + "attached", + "attentive", + "attractive", + "austere", + "authentic", + "authorized", + "automatic", + "avaricious", + "average", + "aware", + "awesome", + "awful", + "awkward", + "babyish", + "bad", + "back", + "baggy", + "bare", + "barren", + "basic", + "beautiful", + "belated", + "beloved", + "beneficial", + "better", + "best", + "bewitched", + "big", + "big-hearted", + "biodegradable", + "bite-sized", + "bitter", + "black", + "black-and-white", + "bland", + "blank", + "blaring", + "bleak", + "blind", + "blissful", + "blond", + "blue", + "blushing", + "bogus", + "boiling", + "bold", + "bony", + "boring", + "bossy", + "both", + "bouncy", + "bountiful", + "bowed", + "brave", + "breakable", + "brief", + "bright", + "brilliant", + "brisk", + "broken", + "bronze", + "brown", + "bruised", + "bubbly", + "bulky", + "bumpy", + "buoyant", + "burdensome", + "burly", + "bustling", + "busy", + "buttery", + "buzzing", + "calculating", + "calm", + "candid", + "canine", + "capital", + "carefree", + "careful", + "careless", + "caring", + "cautious", + "cavernous", + "celebrated", + "charming", + "cheap", + "cheerful", + "cheery", + "chief", + "chilly", + "chubby", + "circular", + "classic", + "clean", + "clear", + "clear-cut", + "clever", + "close", + "closed", + "cloudy", + "clueless", + "clumsy", + "cluttered", + "coarse", + "cold", + "colorful", + "colorless", + "colossal", + "comfortable", + "common", + "compassionate", + "competent", + "complete", + "complex", + "complicated", + "composed", + "concerned", + "concrete", + "confused", + "conscious", + "considerate", + "constant", + "content", + "conventional", + "cooked", + "cool", + "cooperative", + "coordinated", + "corny", + "corrupt", + "costly", + "courageous", + "courteous", + "crafty", + "crazy", + "creamy", + "creative", + "creepy", + "criminal", + "crisp", + "critical", + "crooked", + "crowded", + "cruel", + "crushing", + "cuddly", + "cultivated", + "cultured", + "cumbersome", + "curly", + "curvy", + "cute", + "cylindrical", + "damaged", + "damp", + "dangerous", + "dapper", + "daring", + "darling", + "dark", + "dazzling", + "dead", + "deadly", + "deafening", + "dear", + "dearest", + "decent", + "decimal", + "decisive", + "deep", + "defenseless", + "defensive", + "defiant", + "deficient", + "definite", + "definitive", + "delayed", + "delectable", + "delicious", + "delightful", + "delirious", + "demanding", + "dense", + "dental", + "dependable", + "dependent", + "descriptive", + "deserted", + "detailed", + "determined", + "devoted", + "different", + "difficult", + "digital", + "diligent", + "dim", + "dimpled", + "dimwitted", + "direct", + "disastrous", + "discrete", + "disfigured", + "disgusting", + "disloyal", + "dismal", + "distant", + "downright", + "dreary", + "dirty", + "disguised", + "dishonest", + "dismal", + "distant", + "distinct", + "distorted", + "dizzy", + "dopey", + "doting", + "double", + "downright", + "drab", + "drafty", + "dramatic", + "dreary", + "droopy", + "dry", + "dual", + "dull", + "dutiful", + "each", + "eager", + "earnest", + "early", + "easy", + "easy-going", + "ecstatic", + "edible", + "educated", + "elaborate", + "elastic", + "elated", + "elderly", + "electric", + "elegant", + "elementary", + "elliptical", + "embarrassed", + "embellished", + "eminent", + "emotional", + "empty", + "enchanted", + "enchanting", + "energetic", + "enlightened", + "enormous", + "enraged", + "entire", + "envious", + "equal", + "equatorial", + "essential", + "esteemed", + "ethical", + "euphoric", + "even", + "evergreen", + "everlasting", + "every", + "evil", + "exalted", + "excellent", + "exemplary", + "exhausted", + "excitable", + "excited", + "exciting", + "exotic", + "expensive", + "experienced", + "expert", + "extraneous", + "extroverted", + "extra-large", + "extra-small", + "fabulous", + "failing", + "faint", + "fair", + "faithful", + "fake", + "false", + "familiar", + "famous", + "fancy", + "fantastic", + "far", + "faraway", + "far-flung", + "far-off", + "fast", + "fat", + "fatal", + "fatherly", + "favorable", + "favorite", + "fearful", + "fearless", + "feisty", + "feline", + "female", + "feminine", + "few", + "fickle", + "filthy", + "fine", + "finished", + "firm", + "first", + "firsthand", + "fitting", + "fixed", + "flaky", + "flamboyant", + "flashy", + "flat", + "flawed", + "flawless", + "flickering", + "flimsy", + "flippant", + "flowery", + "fluffy", + "fluid", + "flustered", + "focused", + "fond", + "foolhardy", + "foolish", + "forceful", + "forked", + "formal", + "forsaken", + "forthright", + "fortunate", + "fragrant", + "frail", + "frank", + "frayed", + "free", + "French", + "fresh", + "frequent", + "friendly", + "frightened", + "frightening", + "frigid", + "frilly", + "frizzy", + "frivolous", + "front", + "frosty", + "frozen", + "frugal", + "fruitful", + "full", + "fumbling", + "functional", + "funny", + "fussy", + "fuzzy", + "gargantuan", + "gaseous", + "general", + "generous", + "gentle", + "genuine", + "giant", + "giddy", + "gigantic", + "gifted", + "giving", + "glamorous", + "glaring", + "glass", + "gleaming", + "gleeful", + "glistening", + "glittering", + "gloomy", + "glorious", + "glossy", + "glum", + "golden", + "good", + "good-natured", + "gorgeous", + "graceful", + "gracious", + "grand", + "grandiose", + "granular", + "grateful", + "grave", + "gray", + "great", + "greedy", + "green", + "gregarious", + "grim", + "grimy", + "gripping", + "grizzled", + "gross", + "grotesque", + "grouchy", + "grounded", + "growing", + "growling", + "grown", + "grubby", + "gruesome", + "grumpy", + "guilty", + "gullible", + "gummy", + "hairy", + "half", + "handmade", + "handsome", + "handy", + "happy", + "happy-go-lucky", + "hard", + "hard-to-find", + "harmful", + "harmless", + "harmonious", + "harsh", + "hasty", + "hateful", + "haunting", + "healthy", + "heartfelt", + "hearty", + "heavenly", + "heavy", + "hefty", + "helpful", + "helpless", + "hidden", + "hideous", + "high", + "high-level", + "hilarious", + "hoarse", + "hollow", + "homely", + "honest", + "honorable", + "honored", + "hopeful", + "horrible", + "hospitable", + "hot", + "huge", + "humble", + "humiliating", + "humming", + "humongous", + "hungry", + "hurtful", + "husky", + "icky", + "icy", + "ideal", + "idealistic", + "identical", + "idle", + "idiotic", + "idolized", + "ignorant", + "ill", + "illegal", + "ill-fated", + "ill-informed", + "illiterate", + "illustrious", + "imaginary", + "imaginative", + "immaculate", + "immaterial", + "immediate", + "immense", + "impassioned", + "impeccable", + "impartial", + "imperfect", + "imperturbable", + "impish", + "impolite", + "important", + "impossible", + "impractical", + "impressionable", + "impressive", + "improbable", + "impure", + "inborn", + "incomparable", + "incompatible", + "incomplete", + "inconsequential", + "incredible", + "indelible", + "inexperienced", + "indolent", + "infamous", + "infantile", + "infatuated", + "inferior", + "infinite", + "informal", + "innocent", + "insecure", + "insidious", + "insignificant", + "insistent", + "instructive", + "insubstantial", + "intelligent", + "intent", + "intentional", + "interesting", + "internal", + "international", + "intrepid", + "ironclad", + "irresponsible", + "irritating", + "itchy", + "jaded", + "jagged", + "jam-packed", + "jaunty", + "jealous", + "jittery", + "joint", + "jolly", + "jovial", + "joyful", + "joyous", + "jubilant", + "judicious", + "juicy", + "jumbo", + "junior", + "jumpy", + "juvenile", + "kaleidoscopic", + "keen", + "key", + "kind", + "kindhearted", + "kindly", + "klutzy", + "knobby", + "knotty", + "knowledgeable", + "knowing", + "known", + "kooky", + "kosher", + "lame", + "lanky", + "large", + "last", + "lasting", + "late", + "lavish", + "lawful", + "lazy", + "leading", + "lean", + "leafy", + "left", + "legal", + "legitimate", + "light", + "lighthearted", + "likable", + "likely", + "limited", + "limp", + "limping", + "linear", + "lined", + "liquid", + "little", + "live", + "lively", + "livid", + "loathsome", + "lone", + "lonely", + "long", + "long-term", + "loose", + "lopsided", + "lost", + "loud", + "lovable", + "lovely", + "loving", + "low", + "loyal", + "lucky", + "lumbering", + "luminous", + "lumpy", + "lustrous", + "luxurious", + "mad", + "made-up", + "magnificent", + "majestic", + "major", + "male", + "mammoth", + "married", + "marvelous", + "masculine", + "massive", + "mature", + "meager", + "mealy", + "mean", + "measly", + "meaty", + "medical", + "mediocre", + "medium", + "meek", + "mellow", + "melodic", + "memorable", + "menacing", + "merry", + "messy", + "metallic", + "mild", + "milky", + "mindless", + "miniature", + "minor", + "minty", + "miserable", + "miserly", + "misguided", + "misty", + "mixed", + "modern", + "modest", + "moist", + "monstrous", + "monthly", + "monumental", + "moral", + "mortified", + "motherly", + "motionless", + "mountainous", + "muddy", + "muffled", + "multicolored", + "mundane", + "murky", + "mushy", + "musty", + "muted", + "mysterious", + "naive", + "narrow", + "nasty", + "natural", + "naughty", + "nautical", + "near", + "neat", + "necessary", + "needy", + "negative", + "neglected", + "negligible", + "neighboring", + "nervous", + "new", + "next", + "nice", + "nifty", + "nimble", + "nippy", + "nocturnal", + "noisy", + "nonstop", + "normal", + "notable", + "noted", + "noteworthy", + "novel", + "noxious", + "numb", + "nutritious", + "nutty", + "obedient", + "obese", + "oblong", + "oily", + "oblong", + "obvious", + "occasional", + "odd", + "oddball", + "offbeat", + "offensive", + "official", + "old", + "old-fashioned", + "only", + "open", + "optimal", + "optimistic", + "opulent", + "orange", + "orderly", + "organic", + "ornate", + "ornery", + "ordinary", + "original", + "other", + "our", + "outlying", + "outgoing", + "outlandish", + "outrageous", + "outstanding", + "oval", + "overcooked", + "overdue", + "overjoyed", + "overlooked", + "palatable", + "pale", + "paltry", + "parallel", + "parched", + "partial", + "passionate", + "past", + "pastel", + "peaceful", + "peppery", + "perfect", + "perfumed", + "periodic", + "perky", + "personal", + "pertinent", + "pesky", + "pessimistic", + "petty", + "phony", + "physical", + "piercing", + "pink", + "pitiful", + "plain", + "plaintive", + "plastic", + "playful", + "pleasant", + "pleased", + "pleasing", + "plump", + "plush", + "polished", + "polite", + "political", + "pointed", + "pointless", + "poised", + "poor", + "popular", + "portly", + "posh", + "positive", + "possible", + "potable", + "powerful", + "powerless", + "practical", + "precious", + "present", + "prestigious", + "pretty", + "precious", + "previous", + "pricey", + "prickly", + "primary", + "prime", + "pristine", + "private", + "prize", + "probable", + "productive", + "profitable", + "profuse", + "proper", + "proud", + "prudent", + "punctual", + "pungent", + "puny", + "pure", + "purple", + "pushy", + "putrid", + "puzzled", + "puzzling", + "quaint", + "qualified", + "quarrelsome", + "quarterly", + "queasy", + "querulous", + "questionable", + "quick", + "quick-witted", + "quiet", + "quintessential", + "quirky", + "quixotic", + "quizzical", + "radiant", + "ragged", + "rapid", + "rare", + "rash", + "raw", + "recent", + "reckless", + "rectangular", + "ready", + "real", + "realistic", + "reasonable", + "red", + "reflecting", + "regal", + "regular", + "reliable", + "relieved", + "remarkable", + "remorseful", + "remote", + "repentant", + "required", + "respectful", + "responsible", + "repulsive", + "revolving", + "rewarding", + "rich", + "rigid", + "right", + "ringed", + "ripe", + "roasted", + "robust", + "rosy", + "rotating", + "rotten", + "rough", + "round", + "rowdy", + "royal", + "rubbery", + "rundown", + "ruddy", + "rude", + "runny", + "rural", + "rusty", + "sad", + "safe", + "salty", + "same", + "sandy", + "sane", + "sarcastic", + "sardonic", + "satisfied", + "scaly", + "scarce", + "scared", + "scary", + "scented", + "scholarly", + "scientific", + "scornful", + "scratchy", + "scrawny", + "second", + "secondary", + "second-hand", + "secret", + "self-assured", + "self-reliant", + "selfish", + "sentimental", + "separate", + "serene", + "serious", + "serpentine", + "several", + "severe", + "shabby", + "shadowy", + "shady", + "shallow", + "shameful", + "shameless", + "sharp", + "shimmering", + "shiny", + "shocked", + "shocking", + "shoddy", + "short", + "short-term", + "showy", + "shrill", + "shy", + "sick", + "silent", + "silky", + "silly", + "silver", + "similar", + "simple", + "simplistic", + "sinful", + "single", + "sizzling", + "skeletal", + "skinny", + "sleepy", + "slight", + "slim", + "slimy", + "slippery", + "slow", + "slushy", + "small", + "smart", + "smoggy", + "smooth", + "smug", + "snappy", + "snarling", + "sneaky", + "sniveling", + "snoopy", + "sociable", + "soft", + "soggy", + "solid", + "somber", + "some", + "spherical", + "sophisticated", + "sore", + "sorrowful", + "soulful", + "soupy", + "sour", + "Spanish", + "sparkling", + "sparse", + "specific", + "spectacular", + "speedy", + "spicy", + "spiffy", + "spirited", + "spiteful", + "splendid", + "spotless", + "spotted", + "spry", + "square", + "squeaky", + "squiggly", + "stable", + "staid", + "stained", + "stale", + "standard", + "starchy", + "stark", + "starry", + "steep", + "sticky", + "stiff", + "stimulating", + "stingy", + "stormy", + "straight", + "strange", + "steel", + "strict", + "strident", + "striking", + "striped", + "strong", + "studious", + "stunning", + "stupendous", + "stupid", + "sturdy", + "stylish", + "subdued", + "submissive", + "substantial", + "subtle", + "suburban", + "sudden", + "sugary", + "sunny", + "super", + "superb", + "superficial", + "superior", + "supportive", + "sure-footed", + "surprised", + "suspicious", + "svelte", + "sweaty", + "sweet", + "sweltering", + "swift", + "sympathetic", + "tall", + "talkative", + "tame", + "tan", + "tangible", + "tart", + "tasty", + "tattered", + "taut", + "tedious", + "teeming", + "tempting", + "tender", + "tense", + "tepid", + "terrible", + "terrific", + "testy", + "thankful", + "that", + "these", + "thick", + "thin", + "third", + "thirsty", + "this", + "thorough", + "thorny", + "those", + "thoughtful", + "threadbare", + "thrifty", + "thunderous", + "tidy", + "tight", + "timely", + "tinted", + "tiny", + "tired", + "torn", + "total", + "tough", + "traumatic", + "treasured", + "tremendous", + "tragic", + "trained", + "tremendous", + "triangular", + "tricky", + "trifling", + "trim", + "trivial", + "troubled", + "true", + "trusting", + "trustworthy", + "trusty", + "truthful", + "tubby", + "turbulent", + "twin", + "ugly", + "ultimate", + "unacceptable", + "unaware", + "uncomfortable", + "uncommon", + "unconscious", + "understated", + "unequaled", + "uneven", + "unfinished", + "unfit", + "unfolded", + "unfortunate", + "unhappy", + "unhealthy", + "uniform", + "unimportant", + "unique", + "united", + "unkempt", + "unknown", + "unlawful", + "unlined", + "unlucky", + "unnatural", + "unpleasant", + "unrealistic", + "unripe", + "unruly", + "unselfish", + "unsightly", + "unsteady", + "unsung", + "untidy", + "untimely", + "untried", + "untrue", + "unused", + "unusual", + "unwelcome", + "unwieldy", + "unwilling", + "unwitting", + "unwritten", + "upbeat", + "upright", + "upset", + "urban", + "usable", + "used", + "useful", + "useless", + "utilized", + "utter", + "vacant", + "vague", + "vain", + "valid", + "valuable", + "vapid", + "variable", + "vast", + "velvety", + "venerated", + "vengeful", + "verifiable", + "vibrant", + "vicious", + "victorious", + "vigilant", + "vigorous", + "villainous", + "violet", + "violent", + "virtual", + "virtuous", + "visible", + "vital", + "vivacious", + "vivid", + "voluminous", + "wan", + "warlike", + "warm", + "warmhearted", + "warped", + "wary", + "wasteful", + "watchful", + "waterlogged", + "watery", + "wavy", + "wealthy", + "weak", + "weary", + "webbed", + "wee", + "weekly", + "weepy", + "weighty", + "weird", + "welcome", + "well-documented", + "well-groomed", + "well-informed", + "well-lit", + "well-made", + "well-off", + "well-to-do", + "well-worn", + "wet", + "which", + "whimsical", + "whirlwind", + "whispered", + "white", + "whole", + "whopping", + "wicked", + "wide", + "wide-eyed", + "wiggly", + "wild", + "willing", + "wilted", + "winding", + "windy", + "winged", + "wiry", + "wise", + "witty", + "wobbly", + "woeful", + "wonderful", + "wooden", + "woozy", + "wordy", + "worldly", + "worn", + "worried", + "worrisome", + "worse", + "worst", + "worthless", + "worthwhile", + "worthy", + "wrathful", + "wretched", + "writhing", + "wrong", + "wry", + "yawning", + "yearly", + "yellow", + "yellowish", + "young", + "youthful", + "yummy", + "zany", + "zealous", + "zesty", + "zigzag", ] -export function getRandomUsername(): string { - const n = Math.random() * noun.length - const a = Math.random() * adj.length - return `tmp-${a}-${n}` +export function getRandomUsername(): { first: string, second: string } { + const n = Math.floor(Math.random() * noun.length) + const a = Math.floor(Math.random() * adj.length) + return { + first: adj[a], + second: noun[n] + } } export function getRandomPassword(): string { - return encodeCrock(getRandomBytes(16)) + if (bankUiSettings.simplePasswordForRandomAccounts) return "123" + return encodeCrock(getRandomBytes(16)) }
\ No newline at end of file diff --git a/packages/demobank-ui/src/settings.ts b/packages/demobank-ui/src/settings.ts index 6c78d287b..f33bf07e2 100644 --- a/packages/demobank-ui/src/settings.ts +++ b/packages/demobank-ui/src/settings.ts @@ -18,6 +18,8 @@ export interface BankUiSettings { backendBaseURL: string; allowRegistrations: boolean; showDemoNav: boolean; + simplePasswordForRandomAccounts: boolean; + allowRandomAccountCreation: boolean; bankName: string; demoSites: [string, string][]; } @@ -30,6 +32,8 @@ const defaultSettings: BankUiSettings = { allowRegistrations: true, bankName: "Taler Bank", showDemoNav: true, + simplePasswordForRandomAccounts: true, + allowRandomAccountCreation: true, demoSites: [ ["Landing", "https://demo.taler.net/"], ["Bank", "https://bank.demo.taler.net/"], |