From f3fb8be7db6de87dae40d41bd5597a735c800ca1 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 13 Nov 2016 23:30:18 +0100 Subject: restructuring --- pages/confirm-contract.html | 75 ------- pages/confirm-contract.tsx | 234 ---------------------- pages/confirm-create-reserve.html | 93 --------- pages/confirm-create-reserve.tsx | 395 ------------------------------------- pages/debug.html | 13 -- pages/help/empty-wallet.html | 30 --- pages/show-db.html | 15 -- pages/show-db.ts | 57 ------ pages/tree.html | 36 ---- pages/tree.tsx | 400 -------------------------------------- 10 files changed, 1348 deletions(-) delete mode 100644 pages/confirm-contract.html delete mode 100644 pages/confirm-contract.tsx delete mode 100644 pages/confirm-create-reserve.html delete mode 100644 pages/confirm-create-reserve.tsx delete mode 100644 pages/debug.html delete mode 100644 pages/help/empty-wallet.html delete mode 100644 pages/show-db.html delete mode 100644 pages/show-db.ts delete mode 100644 pages/tree.html delete mode 100644 pages/tree.tsx (limited to 'pages') diff --git a/pages/confirm-contract.html b/pages/confirm-contract.html deleted file mode 100644 index 5c6c9a446..000000000 --- a/pages/confirm-contract.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - Taler Wallet: Confirm Reserve Creation - - - - - - - - - - - - - - - - - - - -
-

GNU Taler Wallet

-
-
- - - diff --git a/pages/confirm-contract.tsx b/pages/confirm-contract.tsx deleted file mode 100644 index b5ada6045..000000000 --- a/pages/confirm-contract.tsx +++ /dev/null @@ -1,234 +0,0 @@ -/* - This file is part of TALER - (C) 2015 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 - */ - -/** - * Page shown to the user to confirm entering - * a contract. - * - * @author Florian Dold - */ - - -import {substituteFulfillmentUrl} from "../lib/wallet/helpers"; -import {Contract, AmountJson, IExchangeInfo} from "../lib/wallet/types"; -import {Offer} from "../lib/wallet/wallet"; -import {renderContract, prettyAmount} from "../lib/wallet/renderHtml"; -"use strict"; -import {getExchanges} from "../lib/wallet/wxApi"; - - -interface DetailState { - collapsed: boolean; - exchanges: null|IExchangeInfo[]; -} - -interface DetailProps { - contract: Contract - collapsed: boolean -} - - -class Details extends React.Component { - constructor(props: DetailProps) { - super(props); - console.log("new Details component created"); - this.state = { - collapsed: props.collapsed, - exchanges: null - }; - - console.log("initial state:", this.state); - - this.update(); - } - - async update() { - let exchanges = await getExchanges(); - this.setState({exchanges} as any); - } - - render() { - console.log("details collapsed (state)", this.state.collapsed); - console.log("details collapsed (prop)", this.props.collapsed); - if (this.state.collapsed) { - return ( -
- -
- ); - } else { - return ( -
- -
- Accepted exchanges: -
    - {this.props.contract.exchanges.map( - e =>
  • {`${e.url}: ${e.master_pub}`}
  • )} -
- Exchanges in the wallet: -
    - {(this.state.exchanges || []).map( - (e: IExchangeInfo) => -
  • {`${e.baseUrl}: ${e.masterPublicKey}`}
  • )} -
-
-
); - } - } -} - -interface ContractPromptProps { - offerId: number; -} - -interface ContractPromptState { - offer: any; - error: string|null; - payDisabled: boolean; -} - -class ContractPrompt extends React.Component { - constructor() { - super(); - this.state = { - offer: undefined, - error: null, - payDisabled: true, - } - } - - componentWillMount() { - this.update(); - this.checkPayment(); - } - - componentWillUnmount() { - // FIXME: abort running ops - } - - async update() { - let offer = await this.getOffer(); - this.setState({offer} as any); - this.checkPayment(); - } - - getOffer(): Promise { - return new Promise((resolve, reject) => { - let msg = { - type: 'get-offer', - detail: { - offerId: this.props.offerId - } - }; - chrome.runtime.sendMessage(msg, (resp) => { - resolve(resp); - }); - }) - } - - checkPayment() { - let msg = { - type: 'check-pay', - detail: { - offer: this.state.offer - } - }; - chrome.runtime.sendMessage(msg, (resp) => { - if (resp.error) { - console.log("check-pay error", JSON.stringify(resp)); - switch (resp.error) { - case "coins-insufficient": - this.state.error = i18n`You have insufficient funds of the requested currency in your wallet.`; - break; - default: - this.state.error = `Error: ${resp.error}`; - break; - } - this.state.payDisabled = true; - } else { - this.state.payDisabled = false; - this.state.error = null; - } - this.setState({} as any); - window.setTimeout(() => this.checkPayment(), 500); - }); - } - - doPayment() { - let d = {offer: this.state.offer}; - chrome.runtime.sendMessage({type: 'confirm-pay', detail: d}, (resp) => { - if (resp.error) { - console.log("confirm-pay error", JSON.stringify(resp)); - switch (resp.error) { - case "coins-insufficient": - this.state.error = "You do not have enough coins of the" + - " requested currency."; - break; - default: - this.state.error = `Error: ${resp.error}`; - break; - } - this.setState({} as any); - return; - } - let c = d.offer.contract; - console.log("contract", c); - document.location.href = substituteFulfillmentUrl(c.fulfillment_url, - this.state.offer); - }); - } - - - render() { - if (!this.state.offer) { - return ...; - } - let c = this.state.offer.contract; - return ( -
-
- {renderContract(c)} -
- -
- {(this.state.error ?

{this.state.error}

:

)} -

-
-
- ); - } -} - - -export function main() { - let url = URI(document.location.href); - let query: any = URI.parseQuery(url.query()); - let offerId = JSON.parse(query.offerId); - - ReactDOM.render(, document.getElementById( - "contract")!); -} diff --git a/pages/confirm-create-reserve.html b/pages/confirm-create-reserve.html deleted file mode 100644 index c31a4aa8a..000000000 --- a/pages/confirm-create-reserve.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - Taler Wallet: Select Taler Provider - - - - - - - - - - - - - - - - - - - - - -
-

GNU Taler Wallet

-
-
- - - diff --git a/pages/confirm-create-reserve.tsx b/pages/confirm-create-reserve.tsx deleted file mode 100644 index 833bfed27..000000000 --- a/pages/confirm-create-reserve.tsx +++ /dev/null @@ -1,395 +0,0 @@ -/* - This file is part of TALER - (C) 2015-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 - */ - - -/** - * Page shown to the user to confirm creation - * of a reserve, usually requested by the bank. - * - * @author Florian Dold - */ - -import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers"; -import {AmountJson, CreateReserveResponse} from "../lib/wallet/types"; -import {ReserveCreationInfo, Amounts} from "../lib/wallet/types"; -import {Denomination} from "../lib/wallet/types"; -import {getReserveCreationInfo} from "../lib/wallet/wxApi"; -import {ImplicitStateComponent, StateHolder} from "../lib/components"; - -"use strict"; - - -function delay(delayMs: number, value: T): Promise { - return new Promise((resolve, reject) => { - setTimeout(() => resolve(value), delayMs); - }); -} - -class EventTrigger { - triggerResolve: any; - triggerPromise: Promise; - - constructor() { - this.reset(); - } - - private reset() { - this.triggerPromise = new Promise((resolve, reject) => { - this.triggerResolve = resolve; - }); - } - - trigger() { - this.triggerResolve(false); - this.reset(); - } - - async wait(delayMs: number): Promise { - return await Promise.race([this.triggerPromise, delay(delayMs, true)]); - } -} - - -function renderReserveCreationDetails(rci: ReserveCreationInfo|null) { - if (!rci) { - return

- Details will be displayed when a valid exchange provider URL is entered.

- } - - let denoms = rci.selectedDenoms; - - let countByPub: {[s: string]: number} = {}; - let uniq: Denomination[] = []; - - denoms.forEach((x: Denomination) => { - let c = countByPub[x.denom_pub] || 0; - if (c == 0) { - uniq.push(x); - } - c += 1; - countByPub[x.denom_pub] = c; - }); - - function row(denom: Denomination) { - return ( - - {countByPub[denom.denom_pub] + "x"} - {amountToPretty(denom.value)} - {amountToPretty(denom.fee_withdraw)} - {amountToPretty(denom.fee_refresh)} - {amountToPretty(denom.fee_deposit)} - - ); - } - - let withdrawFeeStr = amountToPretty(rci.withdrawFee); - let overheadStr = amountToPretty(rci.overhead); - - return ( -
-

{`Withdrawal fees: ${withdrawFeeStr}`}

-

{`Rounding loss: ${overheadStr}`}

- - - - - - - - - - {uniq.map(row)} - -
# CoinsValueWithdraw FeeRefresh FeeDeposit fee
-
- ); -} - - -function getSuggestedExchange(currency: string): Promise { - // TODO: make this request go to the wallet backend - // Right now, this is a stub. - const defaultExchange: {[s: string]: string} = { - "KUDOS": "https://exchange.demo.taler.net", - "PUDOS": "https://exchange.test.taler.net", - }; - - let exchange = defaultExchange[currency]; - - if (!exchange) { - exchange = "" - } - - return Promise.resolve(exchange); -} - - -function WithdrawFee(props: {reserveCreationInfo: ReserveCreationInfo|null}): JSX.Element { - if (props.reserveCreationInfo) { - let {overhead, withdrawFee} = props.reserveCreationInfo; - let totalCost = Amounts.add(overhead, withdrawFee).amount; - return

Withdraw fees: {amountToPretty(totalCost)}

; - } - return

; -} - - -interface ExchangeSelectionProps { - suggestedExchangeUrl: string; - amount: AmountJson; - callback_url: string; - wt_types: string[]; -} - - -class ExchangeSelection extends ImplicitStateComponent { - statusString: StateHolder = this.makeState(null); - reserveCreationInfo: StateHolder = this.makeState( - null); - url: StateHolder = this.makeState(null); - detailCollapsed: StateHolder = this.makeState(true); - - updateEvent = new EventTrigger(); - - constructor(props: ExchangeSelectionProps) { - super(props); - this.onUrlChanged(props.suggestedExchangeUrl || null); - } - - - renderAdvanced(): JSX.Element { - if (this.detailCollapsed() && this.url() !== null && !this.statusString()) { - return ( - - ); - } - return ( -

-

Provider Selection

- - this.onUrlChanged((e.target as HTMLInputElement).value)}/> -
- {this.renderStatus()} -

Detailed Fee Structure

- {renderReserveCreationDetails(this.reserveCreationInfo())} -
) - } - - renderFee() { - if (!this.reserveCreationInfo()) { - return "??"; - } - let rci = this.reserveCreationInfo()!; - let totalCost = Amounts.add(rci.overhead, rci.withdrawFee).amount; - return `${amountToPretty(totalCost)}`; - } - - renderFeeStatus() { - if (this.reserveCreationInfo()) { - return ( -

- The exchange provider will charge - {" "} - {this.renderFee()} - {" "} - in fees. -

- ); - } - if (this.url() && !this.statusString()) { - let shortName = URI(this.url()!).host(); - return

- Waiting for a response from - {" "} - {shortName} -

; - } - if (this.statusString()) { - return ( -

- A problem occured, see below. -

- ); - } - return ( -

- Information about fees will be available when an exchange provider is selected. -

- ); - } - - render(): JSX.Element { - return ( -
-

- {"You are about to withdraw "} - {amountToPretty(this.props.amount)} - {" from your bank account into your wallet."} -

- {this.renderFeeStatus()} - -
- {this.renderAdvanced()} -
- ); - } - - - confirmReserve() { - this.confirmReserveImpl(this.reserveCreationInfo()!, - this.url()!, - this.props.amount, - this.props.callback_url); - } - - /** - * Do an update of the reserve creation info, without any debouncing. - */ - async forceReserveUpdate() { - this.reserveCreationInfo(null); - if (!this.url()) { - this.statusString(i18n`Error: URL is empty`); - return; - } - - this.statusString(null); - let parsedUrl = URI(this.url()!); - if (parsedUrl.is("relative")) { - this.statusString(i18n`Error: URL may not be relative`); - return; - } - - try { - let r = await getReserveCreationInfo(this.url()!, - this.props.amount); - console.log("get exchange info resolved"); - this.reserveCreationInfo(r); - console.dir(r); - } catch (e) { - console.log("get exchange info rejected"); - if (e.hasOwnProperty("httpStatus")) { - this.statusString(`Error: request failed with status ${e.httpStatus}`); - } else if (e.hasOwnProperty("errorResponse")) { - let resp = e.errorResponse; - this.statusString(`Error: ${resp.error} (${resp.hint})`); - } - } - } - - reset() { - this.statusString(null); - this.reserveCreationInfo(null); - } - - confirmReserveImpl(rci: ReserveCreationInfo, - exchange: string, - amount: AmountJson, - callback_url: string) { - const d = {exchange, amount}; - const cb = (rawResp: any) => { - if (!rawResp) { - throw Error("empty response"); - } - // FIXME: filter out types that bank/exchange don't have in common - let wire_details = rci.wireInfo; - if (!rawResp.error) { - const resp = CreateReserveResponse.checked(rawResp); - let q: {[name: string]: string|number} = { - wire_details: JSON.stringify(wire_details), - exchange: resp.exchange, - reserve_pub: resp.reservePub, - amount_value: amount.value, - amount_fraction: amount.fraction, - amount_currency: amount.currency, - }; - let url = URI(callback_url).addQuery(q); - if (!url.is("absolute")) { - throw Error("callback url is not absolute"); - } - console.log("going to", url.href()); - document.location.href = url.href(); - } else { - this.reset(); - this.statusString( - `Oops, something went wrong.` + - `The wallet responded with error status (${rawResp.error}).`); - } - }; - chrome.runtime.sendMessage({type: 'create-reserve', detail: d}, cb); - } - - async onUrlChanged(url: string|null) { - this.reset(); - this.url(url); - if (url == undefined) { - return; - } - this.updateEvent.trigger(); - let waited = await this.updateEvent.wait(200); - if (waited) { - // Run the actual update if nobody else preempted us. - this.forceReserveUpdate(); - this.forceUpdate(); - } - } - - renderStatus(): any { - if (this.statusString()) { - return

{this.statusString()}

; - } else if (!this.reserveCreationInfo()) { - return

Checking URL, please wait ...

; - } - return ""; - } -} - -export async function main() { - const url = URI(document.location.href); - const query: any = URI.parseQuery(url.query()); - const amount = AmountJson.checked(JSON.parse(query.amount)); - const callback_url = query.callback_url; - const bank_url = query.bank_url; - const wt_types = JSON.parse(query.wt_types); - - try { - const suggestedExchangeUrl = await getSuggestedExchange(amount.currency); - let args = { - wt_types, - suggestedExchangeUrl, - callback_url, - amount - }; - - ReactDOM.render(, document.getElementById( - "exchange-selection")!); - - } catch (e) { - // TODO: provide more context information, maybe factor it out into a - // TODO:generic error reporting function or component. - document.body.innerText = `Fatal error: "${e.message}".`; - console.error(`got error "${e.message}"`, e); - } -} diff --git a/pages/debug.html b/pages/debug.html deleted file mode 100644 index 221c7380c..000000000 --- a/pages/debug.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Taler Wallet Debugging - - - -

Debug Pages

- Show DB
- Show balance - - - diff --git a/pages/help/empty-wallet.html b/pages/help/empty-wallet.html deleted file mode 100644 index 952bd92b7..000000000 --- a/pages/help/empty-wallet.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - GNU Taler Help - Empty Wallet - - - - - -
-
-
-

Your wallet is empty!

-

You have succeeded with installing the Taler wallet. However, before - you can buy articles using the Taler wallet, you must withdraw electronic coins. - This is typically done by visiting your bank's online banking Web site. There, - you instruct your bank to transfer the funds to a Taler exchange operator. In - return, your wallet will be allowed to withdraw electronic coins.

-

At this stage, we are not aware of any regular exchange operators issuing - coins in well-known currencies. However, to see how Taler would work, you - can visit our "fake" bank at - bank.demo.taler.net to - withdraw coins in the "KUDOS" currency that we created just for - demonstrating the system.

-
-
-
- - diff --git a/pages/show-db.html b/pages/show-db.html deleted file mode 100644 index 024e844ee..000000000 --- a/pages/show-db.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Taler Wallet: Reserve Created - - - - - -

DB Dump

-

-  
-
diff --git a/pages/show-db.ts b/pages/show-db.ts
deleted file mode 100644
index 71e74388b..000000000
--- a/pages/show-db.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015 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 
- */
-
-
-/**
- * Wallet database dump for debugging.
- *
- * @author Florian Dold
- */
-
-function replacer(match: string, pIndent: string, pKey: string, pVal: string,
-                  pEnd: string) {
-  var key = '';
-  var val = '';
-  var str = '';
-  var r = pIndent || '';
-  if (pKey) {
-    r = r + key + pKey.replace(/[": ]/g, '') + ': ';
-  }
-  if (pVal) {
-    r = r + (pVal[0] == '"' ? str : val) + pVal + '';
-  }
-  return r + (pEnd || '');
-}
-
-
-function prettyPrint(obj: any) {
-  var jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg;
-  return JSON.stringify(obj, null as any, 3)
-             .replace(/&/g, '&').replace(/\\"/g, '"')
-             .replace(//g, '>')
-             .replace(jsonLine, replacer);
-}
-
-
-document.addEventListener("DOMContentLoaded", () => {
-  chrome.runtime.sendMessage({type: 'dump-db'}, (resp) => {
-    const el = document.getElementById('dump');
-    if (!el) {
-      throw Error();
-    }
-    el.innerHTML = prettyPrint(resp);
-  });
-});
diff --git a/pages/tree.html b/pages/tree.html
deleted file mode 100644
index 05022e158..000000000
--- a/pages/tree.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-	Taler Wallet: Tree View
-
-	
-	
-
-	
-
-	
-	
-	
-
-	
-	
-	
-	
-
-	
-	
-
-	
-
-        
-          
- - diff --git a/pages/tree.tsx b/pages/tree.tsx deleted file mode 100644 index 6ff15600f..000000000 --- a/pages/tree.tsx +++ /dev/null @@ -1,400 +0,0 @@ -/* - This file is part of TALER - (C) 2016 Inria - - 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 - */ - -/** - * Show contents of the wallet as a tree. - * - * @author Florian Dold - */ - - -import { IExchangeInfo } from "../lib/wallet/types"; -import { ReserveRecord, Coin, PreCoin, Denomination } from "../lib/wallet/types"; -import { ImplicitStateComponent, StateHolder } from "../lib/components"; -import { - getReserves, getExchanges, getCoins, getPreCoins, - refresh -} from "../lib/wallet/wxApi"; -import { prettyAmount, abbrev } from "../lib/wallet/renderHtml"; -import { getTalerStampDate } from "../lib/wallet/helpers"; - -interface ReserveViewProps { - reserve: ReserveRecord; -} - -class ReserveView extends React.Component { - render(): JSX.Element { - let r: ReserveRecord = this.props.reserve; - return ( -
-
    -
  • Key: {r.reserve_pub}
  • -
  • Created: {(new Date(r.created * 1000).toString())}
  • -
  • Current: {r.current_amount ? prettyAmount(r.current_amount!) : "null"}
  • -
  • Requested: {prettyAmount(r.requested_amount)}
  • -
  • Confirmed: {r.confirmed}
  • -
-
- ); - } -} - -interface ReserveListProps { - exchangeBaseUrl: string; -} - -interface ToggleProps { - expanded: StateHolder; -} - -class Toggle extends ImplicitStateComponent { - renderButton() { - let show = () => { - this.props.expanded(true); - this.setState({}); - }; - let hide = () => { - this.props.expanded(false); - this.setState({}); - }; - if (this.props.expanded()) { - return ; - } - return ; - - } - render() { - return ( -
- {this.renderButton()} - {this.props.expanded() ? this.props.children : []} -
); - } -} - - -interface CoinViewProps { - coin: Coin; -} - -interface RefreshDialogProps { - coin: Coin; -} - -class RefreshDialog extends ImplicitStateComponent { - refreshRequested = this.makeState(false); - render(): JSX.Element { - if (!this.refreshRequested()) { - return ( -
- -
- ); - } - return ( -
- Refresh amount: - - -
- ); - } -} - -class CoinView extends React.Component { - render() { - let c = this.props.coin; - return ( -
-
    -
  • Key: {c.coinPub}
  • -
  • Current amount: {prettyAmount(c.currentAmount)}
  • -
  • Denomination: {abbrev(c.denomPub, 20)}
  • -
  • Suspended: {(c.suspended || false).toString()}
  • -
  • -
-
- ); - } -} - - - -interface PreCoinViewProps { - precoin: PreCoin; -} - -class PreCoinView extends React.Component { - render() { - let c = this.props.precoin; - return ( -
-
    -
  • Key: {c.coinPub}
  • -
-
- ); - } -} - -interface CoinListProps { - exchangeBaseUrl: string; -} - -class CoinList extends ImplicitStateComponent { - coins = this.makeState(null); - expanded = this.makeState(false); - - constructor(props: CoinListProps) { - super(props); - this.update(props); - } - - async update(props: CoinListProps) { - let coins = await getCoins(props.exchangeBaseUrl); - this.coins(coins); - } - - componentWillReceiveProps(newProps: CoinListProps) { - this.update(newProps); - } - - render(): JSX.Element { - if (!this.coins()) { - return
...
; - } - return ( -
- Coins ({this.coins() !.length.toString()}) - {" "} - - {this.coins() !.map((c) => )} - -
- ); - } -} - - -interface PreCoinListProps { - exchangeBaseUrl: string; -} - -class PreCoinList extends ImplicitStateComponent { - precoins = this.makeState(null); - expanded = this.makeState(false); - - constructor(props: PreCoinListProps) { - super(props); - this.update(); - } - - async update() { - let precoins = await getPreCoins(this.props.exchangeBaseUrl); - this.precoins(precoins); - } - - render(): JSX.Element { - if (!this.precoins()) { - return
...
; - } - return ( -
- Pre-Coins ({this.precoins() !.length.toString()}) - {" "} - - {this.precoins() !.map((c) => )} - -
- ); - } -} - -interface DenominationListProps { - exchange: IExchangeInfo; -} - -interface ExpanderTextProps { - text: string; -} - -class ExpanderText extends ImplicitStateComponent { - expanded = this.makeState(false); - textArea: any = undefined; - - componentDidUpdate() { - if (this.expanded() && this.textArea) { - this.textArea.focus(); - this.textArea.scrollTop = 0; - } - } - - render(): JSX.Element { - if (!this.expanded()) { - return ( - { this.expanded(true); }}> - {(this.props.text.length <= 10) - ? this.props.text - : ( - - {this.props.text.substring(0,10)} - ... - - ) - } - - ); - } - return ( - - ); - } -} - -class DenominationList extends ImplicitStateComponent { - expanded = this.makeState(false); - - renderDenom(d: Denomination) { - return ( -
-
    -
  • Value: {prettyAmount(d.value)}
  • -
  • Withdraw fee: {prettyAmount(d.fee_withdraw)}
  • -
  • Refresh fee: {prettyAmount(d.fee_refresh)}
  • -
  • Deposit fee: {prettyAmount(d.fee_deposit)}
  • -
  • Refund fee: {prettyAmount(d.fee_refund)}
  • -
  • Start: {getTalerStampDate(d.stamp_start)!.toString()}
  • -
  • Withdraw expiration: {getTalerStampDate(d.stamp_expire_withdraw)!.toString()}
  • -
  • Legal expiration: {getTalerStampDate(d.stamp_expire_legal)!.toString()}
  • -
  • Deposit expiration: {getTalerStampDate(d.stamp_expire_deposit)!.toString()}
  • -
  • Denom pub:
  • -
-
- ); - } - - render(): JSX.Element { - return ( -
- Denominations ({this.props.exchange.active_denoms.length.toString()}) - {" "} - - {this.props.exchange.active_denoms.map((d) => this.renderDenom(d))} - -
- ); - } -} - -class ReserveList extends ImplicitStateComponent { - reserves = this.makeState(null); - expanded = this.makeState(false); - - constructor(props: ReserveListProps) { - super(props); - this.update(); - } - - async update() { - let reserves = await getReserves(this.props.exchangeBaseUrl); - this.reserves(reserves); - } - - render(): JSX.Element { - if (!this.reserves()) { - return
...
; - } - return ( -
- Reserves ({this.reserves() !.length.toString()}) - {" "} - - {this.reserves() !.map((r) => )} - -
- ); - } -} - -interface ExchangeProps { - exchange: IExchangeInfo; -} - -class ExchangeView extends React.Component { - render(): JSX.Element { - let e = this.props.exchange; - return ( -
-
    -
  • Exchange Base Url: {this.props.exchange.baseUrl}
  • -
  • Master public key:
  • -
- - - - -
- ); - } -} - -interface ExchangesListState { - exchanges?: IExchangeInfo[]; -} - -class ExchangesList extends React.Component { - constructor() { - super(); - let port = chrome.runtime.connect(); - port.onMessage.addListener((msg: any) => { - if (msg.notify) { - console.log("got notified"); - this.update(); - } - }); - this.update(); - this.state = {} as any; - } - - async update() { - let exchanges = await getExchanges(); - console.log("exchanges: ", exchanges); - this.setState({ exchanges }); - } - - render(): JSX.Element { - let exchanges = this.state.exchanges; - if (!exchanges) { - return ...; - } - return ( -
- Exchanges ({exchanges.length.toString()}): - {exchanges.map(e => )} -
- ); - } -} - -export function main() { - ReactDOM.render(, document.getElementById("container")!); -} -- cgit v1.2.3