diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-05-30 18:33:28 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-05-30 18:33:28 +0200 |
commit | e5b88ee00392d855b9d343a3dd80afeb33f44d79 (patch) | |
tree | be4a882fbefd8797acfc37e2fb32b80001d37a1c | |
parent | b6df47f25e6db2de0a7563730f8881f935a94f29 (diff) |
skeleton for better RPC types
-rw-r--r-- | src/types.ts | 46 | ||||
-rw-r--r-- | src/wallet.ts | 46 | ||||
-rw-r--r-- | src/webex/messages.ts | 64 | ||||
-rw-r--r-- | src/webex/notify.ts | 64 | ||||
-rw-r--r-- | src/webex/pages/popup.tsx | 6 | ||||
-rw-r--r-- | src/webex/wxApi.ts | 116 | ||||
-rw-r--r-- | src/webex/wxBackend.ts | 6 | ||||
-rw-r--r-- | tsconfig.json | 3 |
8 files changed, 195 insertions, 156 deletions
diff --git a/src/types.ts b/src/types.ts index c4b6c466a..4dee93a10 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1358,3 +1358,49 @@ export type CheckPayResult = "paid" | "payment-possible" | "insufficient-balance * Possible results for confirmPay. */ export type ConfirmPayResult = "paid" | "insufficient-balance"; + + +/** + * Level of detail at which a history + * entry should be shown. + */ +export enum HistoryLevel { + Trace = 1, + Developer = 2, + Expert = 3, + User = 4, +} + + +/* + * Activity history record. + */ +export interface HistoryRecord { + /** + * Type of the history event. + */ + type: string; + + /** + * Time when the activity was recorded. + */ + timestamp: number; + + /** + * Subject of the entry. Used to group multiple history records together. + * Only the latest history record with the same subjectId will be shown. + */ + subjectId?: string; + + /** + * Details used when rendering the history record. + */ + detail: any; + + /** + * Level of detail of the history entry. + */ + level: HistoryLevel; +} + + diff --git a/src/wallet.ts b/src/wallet.ts index 92187d82f..51c99e805 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -60,6 +60,8 @@ import { ExchangeHandle, ExchangeRecord, ExchangeWireFeesRecord, + HistoryLevel, + HistoryRecord, Notifier, OfferRecord, PayCoinInfo, @@ -270,38 +272,6 @@ export class ConfirmReserveRequest { } -/** - * Activity history record. - */ -export interface HistoryRecord { - /** - * Type of the history event. - */ - type: string; - - /** - * Time when the activity was recorded. - */ - timestamp: number; - - /** - * Subject of the entry. Used to group multiple history records together. - * Only the latest history record with the same subjectId will be shown. - */ - subjectId?: string; - - /** - * Details used when rendering the history record. - */ - detail: any; - - /** - * Level of detail of the history entry. - */ - level: HistoryLevel; -} - - interface PayReq { coins: CoinPaySig[]; merchant_pub: string; @@ -324,18 +294,6 @@ interface TransactionRecord { /** - * Level of detail at which a history - * entry should be shown. - */ -export enum HistoryLevel { - Trace = 1, - Developer = 2, - Expert = 3, - User = 4, -} - - -/** * Badge that shows activity for the wallet. */ export interface Badge { diff --git a/src/webex/messages.ts b/src/webex/messages.ts new file mode 100644 index 000000000..58bd1b2b1 --- /dev/null +++ b/src/webex/messages.ts @@ -0,0 +1,64 @@ +/* + This file is part of TALER + (C) 2017 Inria and 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/> + */ + +/** + * Type definitions for messages between content scripts/pages and backend. + */ + +// Messages are already documented in wxApi. +/* tslint:disable:completed-docs */ + +import * as types from "../types"; + +export interface MessageMap { + "balances": { }; + "dump-db": { }; + "import-db": { dump: object }; + "get-tab-cookie": { }; + "ping": { }; + "reset": { }; + "create-reserve": { amount: types.AmountJson; exchange: string }; + "confirm-reserve": { reservePub: string }; + "generate-nonce": { }; + "confirm-pay": { offer: types.OfferRecord; }; + "check-pay": { offer: types.OfferRecord; }; + "query-payment": { }; + "exchange-info": { baseUrl: string }; + "currency-info": { name: string }; + "hash-contract": { contract: object }; + "put-history-entry": { historyEntry: types.HistoryRecord }; + "safe-offer": { offer: types.OfferRecord }; + "reserve-creation-info": { baseUrl: string }; + "get-history": { }; + "get-offer": { offerId: number } + "get-currencies": { }; + "update-currency": { currencyRecord: types.CurrencyRecord }; + "get-reserves": { exchangeBaseUrl: string }; + "get-payback-reserves": { }; + "withdraw-payback-reserve": { reservePub: string }; + "get-precoins": { exchangeBaseUrl: string }; + "get-denoms": { exchangeBaseUrl: string }; + "payback-coin": { coinPub: string }; + "payment-failed": { contractTermsHash: string }; + "payment-succeeded": { contractTermsHash: string; merchantSig: string }; +} + +export type MessageType = keyof MessageMap; + +export class Message<T extends MessageType> { + constructor (public type: T, public detail: MessageMap[T]) { + } +} diff --git a/src/webex/notify.ts b/src/webex/notify.ts index a7796cc8f..9823c5bd2 100644 --- a/src/webex/notify.ts +++ b/src/webex/notify.ts @@ -27,6 +27,8 @@ */ import URI = require("urijs"); +import wxApi = require("./wxApi"); + declare var cloneInto: any; let logVerbose: boolean = false; @@ -40,29 +42,12 @@ if (document.documentElement.getAttribute("data-taler-nojs")) { document.dispatchEvent(new Event("taler-probe-result")); } - interface Handler { type: string; listener: (e: CustomEvent) => void|Promise<void>; } const handlers: Handler[] = []; -function hashContract(contract: string): Promise<string> { - const walletHashContractMsg = { - detail: {contract}, - type: "hash-contract", - }; - return new Promise<string>((resolve, reject) => { - chrome.runtime.sendMessage(walletHashContractMsg, (resp: any) => { - if (!resp.hash) { - console.log("error", resp); - reject(Error("hashing failed")); - } - resolve(resp.hash); - }); - }); -} - function queryPayment(url: string): Promise<any> { const walletMsg = { detail: { url }, @@ -178,6 +163,8 @@ function handlePaymentResponse(walletResp: any) { timeoutHandle = null; err(); } + timeoutHandle = window.setTimeout(onTimeout, 200); + talerPaymentFailed(walletResp.H_contract).then(() => { if (timeoutHandle !== null) { clearTimeout(timeoutHandle); @@ -185,10 +172,8 @@ function handlePaymentResponse(walletResp: any) { } err(); }); - timeoutHandle = window.setTimeout(onTimeout, 200); } - logVerbose && console.log("handling taler-notify-payment: ", walletResp); // Payment timeout in ms. let timeout_ms = 1000; @@ -353,7 +338,7 @@ async function processProposal(proposal: any) { return; } - const contractHash = await hashContract(proposal.data); + const contractHash = await wxApi.hashContract(proposal.data); if (contractHash !== proposal.hash) { console.error("merchant-supplied contract hash is wrong"); @@ -488,7 +473,7 @@ function registerHandlers() { addHandler("taler-query-id", (msg: any, sendResponse: any) => { - // FIXME: maybe include this info in taoer-probe? + // FIXME: maybe include this info in taler-probe? sendResponse({id: chrome.runtime.id}); }); @@ -518,46 +503,21 @@ function registerHandlers() { window.location.href = redirectUrl; }); - addHandler("taler-confirm-reserve", (msg: any, sendResponse: any) => { - const walletMsg = { - detail: { - reservePub: msg.reserve_pub, - }, - type: "confirm-reserve", - }; - chrome.runtime.sendMessage(walletMsg, (resp) => { - sendResponse(); - }); - }); - - - addHandler("taler-confirm-contract", async(msg: any) => { - if (!msg.contract_wrapper) { - console.error("contract wrapper missing"); + addHandler("taler-confirm-reserve", async (msg: any, sendResponse: any) => { + const reservePub = msg.reserve_pub; + if (typeof reservePub !== "string") { + console.error("taler-confirm-reserve expects parameter reserve_pub of type 'string'"); return; } - - const proposal = msg.contract_wrapper; - - processProposal(proposal); + await wxApi.confirmReserve(msg.reserve_pub); + sendResponse(); }); addHandler("taler-pay", async(msg: any, sendResponse: any) => { const resp = await talerPay(msg); sendResponse(resp); }); - - addHandler("taler-payment-failed", async(msg: any, sendResponse: any) => { - await talerPaymentFailed(msg.H_contract); - sendResponse(); - }); - - addHandler("taler-payment-succeeded", async(msg: any, sendResponse: any) => { - await talerPaymentSucceeded(msg); - sendResponse(); - }); } logVerbose && console.log("loading Taler content script"); init(); - diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx index c62a6f8af..54e4f3e2d 100644 --- a/src/webex/pages/popup.tsx +++ b/src/webex/pages/popup.tsx @@ -30,13 +30,11 @@ import * as i18n from "../../i18n"; import { AmountJson, Amounts, + HistoryLevel, + HistoryRecord, WalletBalance, WalletBalanceEntry, } from "../../types"; -import { - HistoryLevel, - HistoryRecord, -} from "../../wallet"; import { abbrev } from "../renderHtml"; diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts index e4684135b..248cb04b5 100644 --- a/src/webex/wxApi.ts +++ b/src/webex/wxApi.ts @@ -37,27 +37,6 @@ import { } from "../types"; -/** - * Query the wallet for the coins that would be used to withdraw - * from a given reserve. - */ -export function getReserveCreationInfo(baseUrl: string, - amount: AmountJson): Promise<ReserveCreationInfo> { - const m = { type: "reserve-creation-info", detail: { baseUrl, amount } }; - return new Promise<ReserveCreationInfo>((resolve, reject) => { - chrome.runtime.sendMessage(m, (resp) => { - if (resp.error) { - console.error("error response", resp); - const e = Error("call to reserve-creation-info failed"); - (e as any).errorResponse = resp; - reject(e); - return; - } - resolve(resp); - }); - }); -} - async function callBackend(type: string, detail?: any): Promise<any> { return new Promise<any>((resolve, reject) => { @@ -73,34 +52,44 @@ async function callBackend(type: string, detail?: any): Promise<any> { /** + * Query the wallet for the coins that would be used to withdraw + * from a given reserve. + */ +export function getReserveCreationInfo(baseUrl: string, + amount: AmountJson): Promise<ReserveCreationInfo> { + return callBackend("reserve-creation-info", { baseUrl, amount }); +} + + +/** * Get all exchanges the wallet knows about. */ -export async function getExchanges(): Promise<ExchangeRecord[]> { - return await callBackend("get-exchanges"); +export function getExchanges(): Promise<ExchangeRecord[]> { + return callBackend("get-exchanges"); } /** * Get all currencies the exchange knows about. */ -export async function getCurrencies(): Promise<CurrencyRecord[]> { - return await callBackend("get-currencies"); +export function getCurrencies(): Promise<CurrencyRecord[]> { + return callBackend("get-currencies"); } /** * Get information about a specific currency. */ -export async function getCurrency(name: string): Promise<CurrencyRecord|null> { - return await callBackend("currency-info", {name}); +export function getCurrency(name: string): Promise<CurrencyRecord|null> { + return callBackend("currency-info", {name}); } /** * Get information about a specific exchange. */ -export async function getExchangeInfo(baseUrl: string): Promise<ExchangeRecord> { - return await callBackend("exchange-info", {baseUrl}); +export function getExchangeInfo(baseUrl: string): Promise<ExchangeRecord> { + return callBackend("exchange-info", {baseUrl}); } @@ -108,72 +97,72 @@ export async function getExchangeInfo(baseUrl: string): Promise<ExchangeRecord> * Replace an existing currency record with the one given. The currency to * replace is specified inside the currency record. */ -export async function updateCurrency(currencyRecord: CurrencyRecord): Promise<void> { - return await callBackend("update-currency", { currencyRecord }); +export function updateCurrency(currencyRecord: CurrencyRecord): Promise<void> { + return callBackend("update-currency", { currencyRecord }); } /** * Get all reserves the wallet has at an exchange. */ -export async function getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> { - return await callBackend("get-reserves", { exchangeBaseUrl }); +export function getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> { + return callBackend("get-reserves", { exchangeBaseUrl }); } /** * Get all reserves for which a payback is available. */ -export async function getPaybackReserves(): Promise<ReserveRecord[]> { - return await callBackend("get-payback-reserves"); +export function getPaybackReserves(): Promise<ReserveRecord[]> { + return callBackend("get-payback-reserves"); } /** * Withdraw the payback that is available for a reserve. */ -export async function withdrawPaybackReserve(reservePub: string): Promise<ReserveRecord[]> { - return await callBackend("withdraw-payback-reserve", { reservePub }); +export function withdrawPaybackReserve(reservePub: string): Promise<ReserveRecord[]> { + return callBackend("withdraw-payback-reserve", { reservePub }); } /** * Get all coins withdrawn from the given exchange. */ -export async function getCoins(exchangeBaseUrl: string): Promise<CoinRecord[]> { - return await callBackend("get-coins", { exchangeBaseUrl }); +export function getCoins(exchangeBaseUrl: string): Promise<CoinRecord[]> { + return callBackend("get-coins", { exchangeBaseUrl }); } /** * Get all precoins withdrawn from the given exchange. */ -export async function getPreCoins(exchangeBaseUrl: string): Promise<PreCoinRecord[]> { - return await callBackend("get-precoins", { exchangeBaseUrl }); +export function getPreCoins(exchangeBaseUrl: string): Promise<PreCoinRecord[]> { + return callBackend("get-precoins", { exchangeBaseUrl }); } /** * Get all denoms offered by the given exchange. */ -export async function getDenoms(exchangeBaseUrl: string): Promise<DenominationRecord[]> { - return await callBackend("get-denoms", { exchangeBaseUrl }); +export function getDenoms(exchangeBaseUrl: string): Promise<DenominationRecord[]> { + return callBackend("get-denoms", { exchangeBaseUrl }); } /** * Start refreshing a coin. */ -export async function refresh(coinPub: string): Promise<void> { - return await callBackend("refresh-coin", { coinPub }); +export function refresh(coinPub: string): Promise<void> { + return callBackend("refresh-coin", { coinPub }); } /** * Request payback for a coin. Only works for non-refreshed coins. */ -export async function payback(coinPub: string): Promise<void> { - return await callBackend("payback-coin", { coinPub }); +export function payback(coinPub: string): Promise<void> { + return callBackend("payback-coin", { coinPub }); } /** @@ -181,20 +170,41 @@ export async function payback(coinPub: string): Promise<void> { * Note that the numeric offer id is not to be confused with * the string order_id from the contract terms. */ -export async function getOffer(offerId: number) { - return await callBackend("get-offer", { offerId }); +export function getOffer(offerId: number) { + return callBackend("get-offer", { offerId }); } /** * Check if payment is possible or already done. */ -export async function checkPay(offer: OfferRecord): Promise<CheckPayResult> { - return await callBackend("check-pay", { offer }); +export function checkPay(offer: OfferRecord): Promise<CheckPayResult> { + return callBackend("check-pay", { offer }); } /** * Pay for an offer. */ -export async function confirmPay(offer: OfferRecord): Promise<ConfirmPayResult> { - return await callBackend("confirm-pay", { offer }); +export function confirmPay(offer: OfferRecord): Promise<ConfirmPayResult> { + return callBackend("confirm-pay", { offer }); +} + +/** + * Hash a contract. Throws if its not a valid contract. + */ +export function hashContract(contract: object): Promise<string> { + return callBackend("confirm-pay", { contract }); +} + +/** + * Save an offer in the wallet. + */ +export function saveOffer(offer: object): Promise<void> { + return callBackend("save-offer", { offer }); +} + +/** + * Mark a reserve as confirmed. + */ +export function confirmReserve(reservePub: string): Promise<void> { + return callBackend("confirm-reserve", { reservePub }); } diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts index eaae41b9f..49f6e7112 100644 --- a/src/webex/wxBackend.ts +++ b/src/webex/wxBackend.ts @@ -44,6 +44,7 @@ import { } from "../wallet"; import { ChromeBadge } from "./chromeBadge"; + import URI = require("urijs"); import Port = chrome.runtime.Port; import MessageSender = chrome.runtime.MessageSender; @@ -300,9 +301,10 @@ function makeHandlers(db: IDBDatabase, async function dispatch(handlers: any, req: any, sender: any, sendResponse: any): Promise<void> { if (!(req.type in handlers)) { - console.error(`Request type ${JSON.stringify(req)} unknown, req ${req.type}`); + console.error(`Request type ${req.type} unknown`); + console.error(`Request was ${req}`); try { - sendResponse({ error: "request unknown" }); + sendResponse({ error: "request unknown", requestType: req.type }); } catch (e) { // might fail if tab disconnected } diff --git a/tsconfig.json b/tsconfig.json index f4250a2c5..2ba62b510 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,6 +50,7 @@ "src/webex/background.ts", "src/webex/chromeBadge.ts", "src/webex/components.ts", + "src/webex/messages.ts", "src/webex/notify.ts", "src/webex/pages/add-auditor.tsx", "src/webex/pages/auditors.tsx", @@ -65,4 +66,4 @@ "src/webex/wxApi.ts", "src/webex/wxBackend.ts" ] -}
\ No newline at end of file +} |