diff options
author | Sebastian <sebasjm@gmail.com> | 2021-09-20 14:05:40 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-09-20 14:05:40 -0300 |
commit | 8cde98947ba1a6d8c7928578b053786c4e5db17f (patch) | |
tree | ea0337748c02d71bd2b2f7555a49b4e74e98d3ff | |
parent | 9a0285ee4b41c63d144de90d345f160adb39f30f (diff) |
manual withdrawal process
15 files changed, 380 insertions, 29 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 9ddf610cd..5345e3bae 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -33,6 +33,7 @@ import { PopupNavigation } from './components/styled' export enum Pages { welcome = '/welcome', balance = '/balance', + manual_withdraw = '/manual-withdraw', settings = '/settings', dev = '/dev', backup = '/backup', diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index 23b0b1b57..0dbf34b5c 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -486,6 +486,33 @@ export const Input = styled.div<{ invalid?: boolean }>` } ` +export const InputWithLabel = styled.div<{ invalid?: boolean }>` + & label { + display: block; + padding: 5px; + color: ${({ invalid }) => !invalid ? 'inherit' : 'red'} + } + & > div { + position: relative; + display: flex; + top: 0px; + bottom: 0px; + + & > div { + position: absolute; + background-color: lightgray; + padding: 5px; + margin: 2px; + } + + & > input { + flex: 1; + padding: 5px; + border-color: ${({ invalid }) => !invalid ? 'inherit' : 'red'} + } + } +` + export const ErrorBox = styled.div` border: 2px solid #f5c6cb; border-radius: 0.25em; diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index b8b8159f3..46451e72c 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -141,7 +141,7 @@ export function View({ details, amount, onWithdraw, terms, reviewing, onReview, } <section> - {terms.status === 'new' && !accepted && + {terms.status === 'new' && !accepted && !reviewing && <ButtonSuccess upperCased disabled={!details.exchangeInfo.baseUrl} diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx index 350d4b861..e3bada8d4 100644 --- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx +++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx @@ -20,20 +20,21 @@ import { i18n } from "@gnu-taler/taler-util"; import { JSX, h } from "preact"; -import { PopupBox, Centered } from "../components/styled/index"; +import { PopupBox, Centered, ButtonPrimary } from "../components/styled/index"; import { BalancesHook, useBalances } from "../hooks/useBalances"; import { PageLink, renderAmount } from "../renderHtml"; -export function BalancePage() { +export function BalancePage({ goToWalletManualWithdraw }: { goToWalletManualWithdraw: () => void }) { const balance = useBalances() - return <BalanceView balance={balance} Linker={PageLink} /> + return <BalanceView balance={balance} Linker={PageLink} goToWalletManualWithdraw={goToWalletManualWithdraw} /> } export interface BalanceViewProps { - balance: BalancesHook, - Linker: typeof PageLink, + balance: BalancesHook; + Linker: typeof PageLink; + goToWalletManualWithdraw: () => void; } -export function BalanceView({ balance, Linker }: BalanceViewProps) { +export function BalanceView({ balance, Linker, goToWalletManualWithdraw }: BalanceViewProps) { if (!balance) { return <span /> } @@ -57,7 +58,9 @@ export function BalanceView({ balance, Linker }: BalanceViewProps) { </i18n.Translate></p> ) } - return <ShowBalances wallet={balance.response} /> + return <ShowBalances wallet={balance.response} + onWithdraw={goToWalletManualWithdraw} + /> } function formatPending(entry: Balance): JSX.Element { @@ -96,7 +99,7 @@ function formatPending(entry: Balance): JSX.Element { } -function ShowBalances({ wallet }: { wallet: BalancesResponse }) { +function ShowBalances({ wallet, onWithdraw }: { wallet: BalancesResponse, onWithdraw: () => void }) { return <PopupBox> <section> <Centered>{wallet.balances.map((entry) => { @@ -113,5 +116,9 @@ function ShowBalances({ wallet }: { wallet: BalancesResponse }) { ); })}</Centered> </section> + <footer> + <div /> + <ButtonPrimary onClick={onWithdraw} >Withdraw</ButtonPrimary> + </footer> </PopupBox> } diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index 15e27486f..4bdc2d888 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -22,8 +22,8 @@ import { setupI18n } from "@gnu-taler/taler-util"; import { createHashHistory } from "history"; -import { render, h } from "preact"; -import Router, { route, Route } from "preact-router"; +import { render, h, VNode } from "preact"; +import Router, { route, Route, getCurrentUrl } from "preact-router"; import { useEffect, useState } from "preact/hooks"; import { DevContextProvider } from "./context/devContext"; import { useTalerActionURL } from "./hooks/useTalerActionURL"; @@ -96,9 +96,16 @@ function Application() { <WalletNavBar /> <div style={{ width: 400, height: 290 }}> <Router history={createHashHistory()}> - <Route path={Pages.balance} component={BalancePage} /> + <Route path={Pages.balance} component={BalancePage} + goToWalletManualWithdraw={() => goToWalletPage(Pages.manual_withdraw)} + /> <Route path={Pages.settings} component={SettingsPage} /> <Route path={Pages.dev} component={DeveloperPage} /> + + <Route path={Pages.transaction} + component={({ tid }: { tid: string }) => goToWalletPage(Pages.transaction.replace(':tid', tid))} + /> + <Route path={Pages.history} component={HistoryPage} /> <Route path={Pages.backup} component={BackupPage} onAddProvider={() => { @@ -123,6 +130,13 @@ function Application() { ); } +function goToWalletPage(page: Pages | string): null { + chrome.tabs.create({ + active: true, + url: chrome.extension.getURL(`/static/wallet.html#${page}`), + }) + return null +} function Redirect({ to }: { to: string }): null { useEffect(() => { diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx index ffc4418e0..712329bf8 100644 --- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx @@ -57,7 +57,7 @@ export function BackupView({ providers, onAddProvider, onSyncAll }: ViewProps): title={provider.name} /> )} - {!providers.length && <Centered style={{marginTop: 100}}> + {!providers.length && <Centered style={{ marginTop: 100 }}> <BoldLight>No backup providers configured</BoldLight> <ButtonSuccess onClick={onAddProvider}><i18n.Translate>Add provider</i18n.Translate></ButtonSuccess> </Centered>} @@ -98,8 +98,8 @@ function BackupLayout(props: TransactionLayoutProps): JSX.Element { <div style={{ color: !props.active ? "grey" : undefined }}> <a href={Pages.provider_detail.replace(':pid', encodeURIComponent(props.id))}><span>{props.title}</span></a> - {dateStr && <SmallText style={{marginTop: 5}}>Last synced: {dateStr}</SmallText>} - {!dateStr && <SmallLightText style={{marginTop: 5}}>Not synced</SmallLightText>} + {dateStr && <SmallText style={{ marginTop: 5 }}>Last synced: {dateStr}</SmallText>} + {!dateStr && <SmallLightText style={{ marginTop: 5 }}>Not synced</SmallLightText>} </div> <div> {props.status?.type === 'paid' ? diff --git a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx index 4846d47f7..e06e884ce 100644 --- a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx @@ -19,21 +19,24 @@ import { Balance, BalancesResponse, i18n } from "@gnu-taler/taler-util"; -import { JSX, h } from "preact"; -import { WalletBox, Centered } from "../components/styled/index"; +import { JSX } from "preact"; +import { ButtonPrimary, Centered, WalletBox } from "../components/styled/index"; import { BalancesHook, useBalances } from "../hooks/useBalances"; import { PageLink, renderAmount } from "../renderHtml"; -export function BalancePage() { +export function BalancePage({ goToWalletManualWithdraw }: { goToWalletManualWithdraw: () => void }) { const balance = useBalances() - return <BalanceView balance={balance} Linker={PageLink} /> + return <BalanceView balance={balance} Linker={PageLink} goToWalletManualWithdraw={goToWalletManualWithdraw} /> } + export interface BalanceViewProps { - balance: BalancesHook, - Linker: typeof PageLink, + balance: BalancesHook; + Linker: typeof PageLink; + goToWalletManualWithdraw: () => void; } -export function BalanceView({ balance, Linker }: BalanceViewProps) { + +export function BalanceView({ balance, Linker, goToWalletManualWithdraw }: BalanceViewProps) { if (!balance) { return <span /> } @@ -57,7 +60,9 @@ export function BalanceView({ balance, Linker }: BalanceViewProps) { </i18n.Translate></p> ) } - return <ShowBalances wallet={balance.response} /> + return <ShowBalances wallet={balance.response} + onWithdraw={goToWalletManualWithdraw} + /> } function formatPending(entry: Balance): JSX.Element { @@ -96,7 +101,7 @@ function formatPending(entry: Balance): JSX.Element { } -function ShowBalances({ wallet }: { wallet: BalancesResponse }) { +function ShowBalances({ wallet, onWithdraw }: { wallet: BalancesResponse, onWithdraw: () => void }) { return <WalletBox> <section> <Centered>{wallet.balances.map((entry) => { @@ -113,5 +118,9 @@ function ShowBalances({ wallet }: { wallet: BalancesResponse }) { ); })}</Centered> </section> + <footer> + <div /> + <ButtonPrimary onClick={onWithdraw} >Withdraw</ButtonPrimary> + </footer> </WalletBox> } diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx new file mode 100644 index 000000000..35da52392 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx @@ -0,0 +1,56 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample } from '../test-utils'; +import { CreateManualWithdraw as TestedComponent } from './CreateManualWithdraw'; + +export default { + title: 'wallet/manual withdraw/creation', + component: TestedComponent, + argTypes: { + } +}; + + +export const InitialState = createExample(TestedComponent, { +}); + +export const WithExchangeFilled = createExample(TestedComponent, { + currency: 'COL', + initialExchange: 'http://exchange.taler:8081', +}); + +export const WithExchangeAndAmountFilled = createExample(TestedComponent, { + currency: 'COL', + initialExchange: 'http://exchange.taler:8081', + initialAmount: '10' +}); + +export const WithExchangeError = createExample(TestedComponent, { + initialExchange: 'http://exchange.tal', + error: 'The exchange url seems invalid' +}); + +export const WithAmountError = createExample(TestedComponent, { + currency: 'COL', + initialExchange: 'http://exchange.taler:8081', + initialAmount: 'e' +}); diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx new file mode 100644 index 000000000..be2cbe41d --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx @@ -0,0 +1,57 @@ +import { AmountJson, Amounts } from "@gnu-taler/taler-util"; +import { VNode } from "preact"; +import { useEffect, useRef, useState } from "preact/hooks"; +import { ErrorMessage } from "../components/ErrorMessage"; +import { ButtonPrimary, Input, InputWithLabel, LightText, WalletBox } from "../components/styled"; + +export interface Props { + error: string | undefined; + currency: string | undefined; + initialExchange?: string; + initialAmount?: string; + onExchangeChange: (exchange: string) => void; + onCreate: (exchangeBaseUrl: string, amount: AmountJson) => Promise<void>; +} + +export function CreateManualWithdraw({ onExchangeChange, initialExchange, initialAmount, error, currency, onCreate }: Props): VNode { + const [exchange, setExchange] = useState(initialExchange || ""); + const [amount, setAmount] = useState(initialAmount || ""); + const parsedAmount = Amounts.parse(`${currency}:${amount}`) + + let timeout = useRef<number | undefined>(undefined); + useEffect(() => { + if (timeout) window.clearTimeout(timeout.current) + timeout.current = window.setTimeout(async () => { + onExchangeChange(exchange) + }, 1000); + }, [exchange]) + + + return ( + <WalletBox> + <section> + <ErrorMessage title={error && "Can't create the reserve"} description={error} /> + <h2>Manual Withdrawal</h2> + <LightText>Choose a exchange to create a reserve and then fill the reserve to withdraw the coins</LightText> + <p> + <Input invalid={!!exchange && !currency}> + <label>Exchange</label> + <input type="text" placeholder="https://" value={exchange} onChange={(e) => setExchange(e.currentTarget.value)} /> + <small>http://exchange.taler:8081</small> + </Input> + {currency && <InputWithLabel invalid={!!amount && !parsedAmount}> + <label>Amount</label> + <div> + <div>{currency}</div> + <input type="number" style={{ paddingLeft: `${currency.length}em` }} value={amount} onChange={e => setAmount(e.currentTarget.value)} /> + </div> + </InputWithLabel>} + </p> + </section> + <footer> + <div /> + <ButtonPrimary disabled={!parsedAmount || !exchange} onClick={() => onCreate(exchange, parsedAmount!)}>Create</ButtonPrimary> + </footer> + </WalletBox> + ); +} diff --git a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx new file mode 100644 index 000000000..d4daefc2e --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx @@ -0,0 +1,71 @@ +/* + This file is part of TALER + (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ + + +import { VNode } from "preact"; +import { useEffect, useRef, useState } from "preact/hooks"; +import { CreateManualWithdraw } from "./CreateManualWithdraw"; +import * as wxApi from '../wxApi' +import { AcceptManualWithdrawalResult, AmountJson, Amounts } from "@gnu-taler/taler-util"; +import { ReserveCreated } from "./ReserveCreated.js"; + +interface Props { + +} + +export function ManualWithdrawPage({ }: Props): VNode { + const [success, setSuccess] = useState<AcceptManualWithdrawalResult | undefined>(undefined) + const [currency, setCurrency] = useState<string | undefined>(undefined) + const [error, setError] = useState<string | undefined>(undefined) + + async function onExchangeChange(exchange: string | undefined) { + if (!exchange) return + try { + const r = await fetch(`${exchange}/keys`) + const j = await r.json() + setCurrency(j.currency) + } catch (e) { + setError('The exchange url seems invalid') + setCurrency(undefined) + } + } + + async function doCreate(exchangeBaseUrl: string, amount: AmountJson) { + try { + const resp = await wxApi.acceptManualWithdrawal(exchangeBaseUrl, Amounts.stringify(amount)) + setSuccess(resp) + } catch (e) { + if (e instanceof Error) { + setError(e.message) + } else { + setError('unexpected error') + } + setSuccess(undefined) + } + } + + if (success) { + return <ReserveCreated reservePub={success.reservePub} paytos={success.exchangePaytoUris} onBack={() => {}}/> + } + + return <CreateManualWithdraw + error={error} currency={currency} + onCreate={doCreate} onExchangeChange={onExchangeChange} + />; +} + + + diff --git a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx new file mode 100644 index 000000000..ca524f4e2 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.stories.tsx @@ -0,0 +1,40 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample } from '../test-utils'; +import { ReserveCreated as TestedComponent } from './ReserveCreated'; + +export default { + title: 'wallet/manual withdraw/reserve created', + component: TestedComponent, + argTypes: { + } +}; + + +export const InitialState = createExample(TestedComponent, { + reservePub: 'ASLKDJQWLKEJASLKDJSADLKASJDLKSADJ', + paytos: [ + 'payto://x-taler-bank/bank.taler:5882/exchangeminator?amount=COL%3A1&message=Taler+Withdrawal+A05AJGMFNSK4Q62NXR2FKNDB1J4EXTYQTE7VA4M9GZQ4TR06YBNG', + 'payto://x-taler-bank/international-bank.com/myaccount?amount=COL%3A1&message=Taler+Withdrawal+TYQTE7VA4M9GZQ4TR06YBNGA05AJGMFNSK4Q62NXR2FKNDB1J4EX', + ] +}); + diff --git a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx new file mode 100644 index 000000000..e01336e02 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx @@ -0,0 +1,41 @@ +import { Fragment, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { QR } from "../components/QR"; +import { ButtonBox, FontIcon, WalletBox } from "../components/styled"; + +export interface Props { + reservePub: string; + paytos: string[]; + onBack: () => void; +} + +export function ReserveCreated({ reservePub, paytos, onBack }: Props): VNode { + const [opened, setOpened] = useState(-1) + return ( + <WalletBox> + <section> + <h2>Reserve created!</h2> + <p>Now you need to send money to the exchange to one of the following accounts</p> + <p>To complete the setup of the reserve, you must now initiate a wire transfer using the given wire transfer subject and crediting the specified amount to the indicated account of the exchange.</p> + </section> + <section> + <ul> + {paytos.map((href, idx) => { + const url = new URL(href) + return <li key={idx}><p> + <a href="" onClick={(e) => { setOpened(o => o === idx ? -1 : idx); e.preventDefault() }}>{url.pathname}</a> + {opened === idx && <Fragment> + <p>If your system supports RFC 8905, you can do this by opening <a href={href}>this URI</a> or scan the QR with your wallet</p> + <QR text={href} /> + </Fragment>} + </p></li> + })} + </ul> + </section> + <footer> + <ButtonBox onClick={onBack}><FontIcon>←</FontIcon></ButtonBox> + <div /> + </footer> + </WalletBox> + ); +} diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 435753725..052b77dd0 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -51,7 +51,7 @@ export function TransactionPage({ tid }: { tid: string; }): JSX.Element { transaction={transaction} onDelete={() => wxApi.deleteTransaction(tid).then(_ => history.go(-1))} onRetry={() => wxApi.retryTransaction(tid).then(_ => history.go(-1))} - onBack={() => { history.go(-1); }} />; + onBack={() => { route(Pages.history) }} />; } export interface WalletTransactionProps { diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx index aa007786c..023ee94c5 100644 --- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx @@ -41,6 +41,8 @@ import { SettingsPage } from "./wallet/Settings"; import { TransactionPage } from './wallet/Transaction'; import { WelcomePage } from "./wallet/Welcome"; import { BackupPage } from './wallet/BackupPage'; +import { DeveloperPage } from "./popup/Debug.js"; +import { ManualWithdrawPage } from "./wallet/ManualWithdrawPage.js"; function main(): void { @@ -52,7 +54,9 @@ function main(): void { render(<Application />, container); } catch (e) { console.error("got error", e); - document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`; + if (e instanceof Error) { + document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`; + } } } @@ -65,10 +69,10 @@ if (document.readyState === "loading") { } function withLogoAndNavBar(Component: any) { - return () => <Fragment> + return (props: any) => <Fragment> <LogoHeader /> <WalletNavBar /> - <Component /> + <Component {...props} /> </Fragment> } @@ -81,14 +85,20 @@ function Application() { <Route path={Pages.history} component={withLogoAndNavBar(HistoryPage)} /> <Route path={Pages.transaction} component={withLogoAndNavBar(TransactionPage)} /> - <Route path={Pages.balance} component={withLogoAndNavBar(BalancePage)} /> + <Route path={Pages.balance} component={withLogoAndNavBar(BalancePage)} + goToWalletManualWithdraw={() => route(Pages.manual_withdraw)} + /> <Route path={Pages.settings} component={withLogoAndNavBar(SettingsPage)} /> <Route path={Pages.backup} component={withLogoAndNavBar(BackupPage)} /> + <Route path={Pages.manual_withdraw} component={withLogoAndNavBar(ManualWithdrawPage)} /> + <Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} /> <Route path={Pages.payback} component={() => <div>no yet implemented</div>} /> <Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} /> + <Route path={Pages.dev} component={withLogoAndNavBar(DeveloperPage)} /> + {/** call to action */} <Route path={Pages.pay} component={PayPage} /> <Route path={Pages.refund} component={RefundPage} /> diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index 63774b00b..8a0881a6c 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -40,6 +40,9 @@ import { SetWalletDeviceIdRequest, GetExchangeWithdrawalInfo, AcceptExchangeTosRequest, + AcceptManualWithdrawalResult, + AcceptManualWithdrawalRequest, + AmountJson, } from "@gnu-taler/taler-util"; import { AddBackupProviderRequest, BackupProviderState, OperationFailedError, RemoveBackupProviderRequest } from "@gnu-taler/taler-wallet-core"; import { BackupInfo } from "@gnu-taler/taler-wallet-core"; @@ -252,6 +255,21 @@ export function acceptWithdrawal( }); } +/** + * Create a reserve into the exchange that expect the amount indicated + * @param exchangeBaseUrl + * @param amount + * @returns + */ +export function acceptManualWithdrawal( + exchangeBaseUrl: string, + amount: string, +): Promise<AcceptManualWithdrawalResult> { + return callBackend("acceptManualWithdrawal", { + amount, exchangeBaseUrl + }); +} + export function setExchangeTosAccepted( exchangeBaseUrl: string, etag: string | undefined |