aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-30 18:33:28 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-30 18:33:28 +0200
commite5b88ee00392d855b9d343a3dd80afeb33f44d79 (patch)
treebe4a882fbefd8797acfc37e2fb32b80001d37a1c
parentb6df47f25e6db2de0a7563730f8881f935a94f29 (diff)
skeleton for better RPC types
-rw-r--r--src/types.ts46
-rw-r--r--src/wallet.ts46
-rw-r--r--src/webex/messages.ts64
-rw-r--r--src/webex/notify.ts64
-rw-r--r--src/webex/pages/popup.tsx6
-rw-r--r--src/webex/wxApi.ts116
-rw-r--r--src/webex/wxBackend.ts6
-rw-r--r--tsconfig.json3
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
+}