diff options
5 files changed, 235 insertions, 55 deletions
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index aac3b546c..7785e19ef 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -311,14 +311,17 @@ async function sendMessageToWalletBackground( chrome.runtime.sendMessage( { operation, payload, id: `id_${i++ % 1000}` }, (backgroundResponse) => { - logger.trace("BUG: got response from background", backgroundResponse); + logger.trace( + "BUG: got response from background", + backgroundResponse, + chrome.runtime.lastError, + ); if (chrome.runtime.lastError) { reject(chrome.runtime.lastError.message); + } else { + resolve(backgroundResponse); } - // const apiResponse = JSON.parse(resp) - resolve(backgroundResponse); - // return true to keep the channel open return true; }, @@ -355,13 +358,21 @@ function sendMessageToAllChannels(message: MessageFromBackend): void { function registerAllIncomingConnections(): void { chrome.runtime.onConnect.addListener((port) => { - allPorts.push(port); - port.onDisconnect.addListener((discoPort) => { - const idx = allPorts.indexOf(discoPort); - if (idx >= 0) { - allPorts.splice(idx, 1); - } - }); + try { + allPorts.push(port); + port.onDisconnect.addListener((discoPort) => { + try { + const idx = allPorts.indexOf(discoPort); + if (idx >= 0) { + allPorts.splice(idx, 1); + } + } catch (e) { + logger.error("error trying to remove connection", e); + } + }); + } catch (e) { + logger.error("error trying to save incoming connection", e); + } }); } @@ -375,7 +386,11 @@ function listenToAllChannels( chrome.runtime.onMessage.addListener((m, s, c) => { cb(m, s, (apiResponse) => { logger.trace("BUG: sending response to client", apiResponse); - c(apiResponse); + try { + c(apiResponse); + } catch (e) { + logger.error("wallet operation ended with error", e); + } }); // keep the connection open diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts index 1bb4fb314..10e44ce7d 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts @@ -77,7 +77,11 @@ export namespace State { export interface Comparing extends BaseInfo { status: "comparing"; - pairTimeline: DenomOperationMap<FeeDescriptionPair[]>; + coinOperationTimeline: DenomOperationMap<FeeDescriptionPair[]>; + wireFeeTimeline: Record<string, FeeDescriptionPair[]>; + globalFeeTimeline: FeeDescriptionPair[]; + missingWireTYpe: string[]; + newWireType: string[]; onReset: ButtonHandler; onSelect: ButtonHandler; } diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts index 378556b94..3c10febd9 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts @@ -155,7 +155,7 @@ export function useComponentState({ } //this may be expensive, useMemo - const pairTimeline: DenomOperationMap<FeeDescription[]> = { + const coinOperationTimeline: DenomOperationMap<FeeDescription[]> = { deposit: createPairTimeline( selected.denomFees.deposit, original.denomFees.deposit, @@ -174,6 +174,36 @@ export function useComponentState({ ), }; + const globalFeeTimeline = createPairTimeline( + selected.globalFees, + original.globalFees, + ); + + const allWireType = Object.keys(selected.transferFees).concat( + Object.keys(original.transferFees), + ); + + const wireFeeTimeline: Record<string, FeeDescription[]> = {}; + + const missingWireTYpe: string[] = []; + const newWireType: string[] = []; + + for (const wire of allWireType) { + const selectedWire = selected.transferFees[wire]; + const originalWire = original.transferFees[wire]; + + if (!selectedWire) { + newWireType.push(wire); + continue; + } + if (!originalWire) { + missingWireTYpe.push(wire); + continue; + } + + wireFeeTimeline[wire] = createPairTimeline(selectedWire, originalWire); + } + return { status: "comparing", exchanges: { @@ -205,6 +235,10 @@ export function useComponentState({ }, }, selected, - pairTimeline, + coinOperationTimeline, + wireFeeTimeline, + globalFeeTimeline, + missingWireTYpe, + newWireType, }; } diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/stories.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/stories.tsx index 3706359a8..05765b50a 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/stories.tsx @@ -120,12 +120,16 @@ export const ComparingBitcoin = createExample(ComparingView, { onShowTerms: {}, onSelect: {}, error: undefined, - pairTimeline: { + coinOperationTimeline: { deposit: [], refresh: [], refund: [], withdraw: [], }, + globalFeeTimeline: [], + newWireType: [], + missingWireTYpe: [], + wireFeeTimeline: {}, }); export const ComparingKudos = createExample(ComparingView, { exchanges: { @@ -144,12 +148,16 @@ export const ComparingKudos = createExample(ComparingView, { onShowTerms: {}, onSelect: {}, error: undefined, - pairTimeline: { + coinOperationTimeline: { deposit: [], refresh: [], refund: [], withdraw: [], }, + globalFeeTimeline: [], + newWireType: [], + missingWireTYpe: [], + wireFeeTimeline: {}, }); function timelineExample() { diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/views.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/views.tsx index 95ab55261..26ff2c0d3 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/views.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/views.tsx @@ -178,7 +178,11 @@ export function ComparingView({ selected, onReset, onSelect, - pairTimeline, + coinOperationTimeline, + globalFeeTimeline, + wireFeeTimeline, + missingWireTYpe, + newWireType, onShowPrivacy, onShowTerms, }: State.Comparing): VNode { @@ -249,9 +253,16 @@ export function ComparingView({ </section> <section> <h2> - <i18n.Translate>Operations</i18n.Translate> + <i18n.Translate>Coin operations</i18n.Translate> </h2> <p> + <i18n.Translate> + Every operation in this section may be different by denomination + value and is valid for a period of time. The exchange will charge + the indicated amount every time a coin is used in such operation. + </i18n.Translate> + </p> + <p> <i18n.Translate>Deposits</i18n.Translate> </p> <FeeDescriptionTable> @@ -274,7 +285,7 @@ export function ComparingView({ </thead> <tbody> <RenderFeePairByValue - list={pairTimeline.deposit} + list={coinOperationTimeline.deposit} sorting={(a, b) => Number(a) - Number(b)} /> </tbody> @@ -290,7 +301,10 @@ export function ComparingView({ <i18n.Translate>Denomination</i18n.Translate> </th> <th class="fee"> - <i18n.Translate>Fee</i18n.Translate> + <i18n.Translate>Current</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Selected</i18n.Translate> </th> <th> <i18n.Translate>Until</i18n.Translate> @@ -299,7 +313,7 @@ export function ComparingView({ </thead> <tbody> <RenderFeePairByValue - list={pairTimeline.withdraw} + list={coinOperationTimeline.withdraw} sorting={(a, b) => Number(a) - Number(b)} /> </tbody> @@ -315,7 +329,10 @@ export function ComparingView({ <i18n.Translate>Denomination</i18n.Translate> </th> <th class="fee"> - <i18n.Translate>Fee</i18n.Translate> + <i18n.Translate>Current</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Selected</i18n.Translate> </th> <th> <i18n.Translate>Until</i18n.Translate> @@ -324,7 +341,7 @@ export function ComparingView({ </thead> <tbody> <RenderFeePairByValue - list={pairTimeline.refund} + list={coinOperationTimeline.refund} sorting={(a, b) => Number(a) - Number(b)} /> </tbody> @@ -340,7 +357,10 @@ export function ComparingView({ <i18n.Translate>Denomination</i18n.Translate> </th> <th class="fee"> - <i18n.Translate>Fee</i18n.Translate> + <i18n.Translate>Current</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Selected</i18n.Translate> </th> <th> <i18n.Translate>Until</i18n.Translate> @@ -349,13 +369,141 @@ export function ComparingView({ </thead> <tbody> <RenderFeePairByValue - list={pairTimeline.refresh} + list={coinOperationTimeline.refresh} sorting={(a, b) => Number(a) - Number(b)} /> </tbody> </FeeDescriptionTable>{" "} </section> <section> + <h2> + <i18n.Translate>Transfer operations</i18n.Translate> + </h2> + <p> + <i18n.Translate> + Every operation in this section may be different by transfer type + and is valid for a period of time. The exchange will charge the + indicated amount every time a transfer is made. + </i18n.Translate> + </p> + {missingWireTYpe.map((type) => { + return ( + <p key={type}> + Wire <b>{type}</b> is not supported for this exchange. + </p> + ); + })} + {newWireType.map((type) => { + return ( + <Fragment key={type}> + <p> + Wire <b>{type}</b> is not supported for the previous exchange. + </p> + <FeeDescriptionTable> + <thead> + <tr> + <th> </th> + <th> + <i18n.Translate>Operation</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Fee</i18n.Translate> + </th> + <th> + <i18n.Translate>Until</i18n.Translate> + </th> + </tr> + </thead> + <tbody> + <RenderFeeDescriptionByValue + list={selected.transferFees[type]} + /> + </tbody> + </FeeDescriptionTable> + </Fragment> + ); + })} + {Object.entries(wireFeeTimeline).map(([type, fees], idx) => { + return ( + <Fragment key={idx}> + <p>{type}</p> + <FeeDescriptionTable> + <thead> + <tr> + <th> </th> + <th> + <i18n.Translate>Operation</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Current</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Selected</i18n.Translate> + </th> + <th> + <i18n.Translate>Until</i18n.Translate> + </th> + </tr> + </thead> + <tbody> + <RenderFeePairByValue + list={fees} + sorting={(a, b) => a.localeCompare(b)} + /> + </tbody> + </FeeDescriptionTable> + </Fragment> + ); + })} + </section> + <section> + <h2> + <i18n.Translate>Wallet operations</i18n.Translate> + </h2> + <p> + <i18n.Translate> + Every operation in this section may be different by transfer type + and is valid for a period of time. The exchange will charge the + indicated amount every time a transfer is made. + </i18n.Translate> + </p> + <FeeDescriptionTable> + <thead> + <tr> + <th> </th> + <th> + <i18n.Translate>Feature</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Current</i18n.Translate> + </th> + <th class="fee"> + <i18n.Translate>Selected</i18n.Translate> + </th> + <th> + <i18n.Translate>Until</i18n.Translate> + </th> + </tr> + </thead> + <tbody> + <RenderFeePairByValue + list={globalFeeTimeline} + sorting={(a, b) => a.localeCompare(b)} + /> + </tbody> + </FeeDescriptionTable> + </section> + <section> + <ButtonGroupFooter> + <Button onClick={onShowPrivacy.onClick} variant="outlined"> + Privacy policy + </Button> + <Button onClick={onShowTerms.onClick} variant="outlined"> + Terms of service + </Button> + </ButtonGroupFooter> + </section> + <section> <ButtonGroupFooter> <Button onClick={onShowPrivacy.onClick} variant="outlined"> Privacy policy @@ -755,35 +903,6 @@ function RenderFeePairByValue({ .sort(sorting) .map((i, idx) => <FeePairRowsGroup key={idx} infos={grouped[i]} />); return <Fragment>{p}</Fragment>; - - // return ( - // <Fragment> - // { - // list.reduce( - // (prev, info, idx) => { - // const next = idx >= list.length - 1 ? undefined : list[idx + 1]; - - // const nextIsMoreInfo = - // next !== undefined && next.group === info.group; - - // prev.rows.push(info); - - // if (nextIsMoreInfo) { - // return prev; - // } - - // // prev.rows = []; - // prev.views.push(<FeePairRowsGroup infos={prev.rows} />); - // return prev; - // }, - // { rows: [], views: [] } as { - // rows: FeeDescriptionPair[]; - // views: h.JSX.Element[]; - // }, - // ).views - // } - // </Fragment> - // ); } /** * |