aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-02-23 14:07:53 +0100
committerFlorian Dold <florian.dold@gmail.com>2016-02-23 14:07:59 +0100
commit5591077fe9241def5fa33fc90a24681c8b7b0976 (patch)
treee4020c487d20fd7bfd7b2256ee8f2d88861dcc6a
parent718f81bcd858bd50373066845727b0cf520ccd06 (diff)
downloadwallet-core-5591077fe9241def5fa33fc90a24681c8b7b0976.tar.xz
repurchase detection
-rw-r--r--extension/content_scripts/notify.js34
-rw-r--r--extension/content_scripts/notify.ts38
-rw-r--r--extension/lib/wallet/db.ts15
-rw-r--r--extension/lib/wallet/query.ts23
-rw-r--r--extension/lib/wallet/types.ts7
-rw-r--r--extension/lib/wallet/wallet.ts30
-rw-r--r--extension/lib/wallet/wxMessaging.ts5
7 files changed, 139 insertions, 13 deletions
diff --git a/extension/content_scripts/notify.js b/extension/content_scripts/notify.js
index 4749fe9bf..d81732f10 100644
--- a/extension/content_scripts/notify.js
+++ b/extension/content_scripts/notify.js
@@ -65,12 +65,36 @@ var TalerNotify;
document.addEventListener("taler-contract", function (e) {
// XXX: the merchant should just give us the parsed data ...
var offer = JSON.parse(e.detail);
- var uri = URI(chrome.extension.getURL("pages/confirm-contract.html"));
- var params = {
- offer: JSON.stringify(offer),
- merchantPageUrl: document.location.href,
+ if (!offer.contract) {
+ console.error("contract field missing");
+ return;
+ }
+ var msg = {
+ type: "check-repurchase",
+ detail: {
+ contract: offer.contract
+ },
};
- document.location.href = uri.query(params).href();
+ chrome.runtime.sendMessage(msg, function (resp) {
+ if (resp.error) {
+ console.error("wallet backend error", resp);
+ return;
+ }
+ if (resp.isRepurchase) {
+ console.log("doing repurchase");
+ console.assert(resp.existingFulfillmentUrl);
+ console.assert(resp.existingContractHash);
+ window.location.href = subst(resp.existingFulfillmentUrl, resp.existingContractHash);
+ }
+ else {
+ var uri = URI(chrome.extension.getURL("pages/confirm-contract.html"));
+ var params = {
+ offer: JSON.stringify(offer),
+ merchantPageUrl: document.location.href,
+ };
+ document.location.href = uri.query(params).href();
+ }
+ });
});
document.addEventListener('taler-execute-payment', function (e) {
console.log("got taler-execute-payment in content page");
diff --git a/extension/content_scripts/notify.ts b/extension/content_scripts/notify.ts
index 9a64bcf0c..d300dbc03 100644
--- a/extension/content_scripts/notify.ts
+++ b/extension/content_scripts/notify.ts
@@ -77,12 +77,40 @@ namespace TalerNotify {
document.addEventListener("taler-contract", function(e: CustomEvent) {
// XXX: the merchant should just give us the parsed data ...
let offer = JSON.parse(e.detail);
- let uri = URI(chrome.extension.getURL("pages/confirm-contract.html"));
- let params = {
- offer: JSON.stringify(offer),
- merchantPageUrl: document.location.href,
+
+ if (!offer.contract) {
+ console.error("contract field missing");
+ return;
+ }
+
+ let msg = {
+ type: "check-repurchase",
+ detail: {
+ contract: offer.contract
+ },
};
- document.location.href = uri.query(params).href();
+
+ chrome.runtime.sendMessage(msg, (resp) => {
+ if (resp.error) {
+ console.error("wallet backend error", resp);
+ return;
+ }
+ if (resp.isRepurchase) {
+ console.log("doing repurchase");
+ console.assert(resp.existingFulfillmentUrl);
+ console.assert(resp.existingContractHash);
+ window.location.href = subst(resp.existingFulfillmentUrl,
+ resp.existingContractHash);
+
+ } else {
+ let uri = URI(chrome.extension.getURL("pages/confirm-contract.html"));
+ let params = {
+ offer: JSON.stringify(offer),
+ merchantPageUrl: document.location.href,
+ };
+ document.location.href = uri.query(params).href();
+ }
+ });
});
diff --git a/extension/lib/wallet/db.ts b/extension/lib/wallet/db.ts
index 106f1f34c..c7621c5ff 100644
--- a/extension/lib/wallet/db.ts
+++ b/extension/lib/wallet/db.ts
@@ -51,10 +51,21 @@ export function openTalerDb(): Promise<IDBDatabase> {
db.createObjectStore("denoms", {keyPath: "denomPub"});
const coins = db.createObjectStore("coins", {keyPath: "coinPub"});
coins.createIndex("mintBaseUrl", "mintBaseUrl");
- db.createObjectStore("transactions", {keyPath: "contractHash"});
+ const transactions = db.createObjectStore("transactions",
+ {keyPath: "contractHash"});
+ transactions.createIndex("repurchase",
+ [
+ "contract.merchant_pub",
+ "contract.repurchase_correlation_id"
+ ]);
+
db.createObjectStore("precoins",
{keyPath: "coinPub", autoIncrement: true});
- const history = db.createObjectStore("history", {keyPath: "id", autoIncrement: true});
+ const history = db.createObjectStore("history",
+ {
+ keyPath: "id",
+ autoIncrement: true
+ });
history.createIndex("timestamp", "timestamp");
break;
}
diff --git a/extension/lib/wallet/query.ts b/extension/lib/wallet/query.ts
index b82c85189..62411dab3 100644
--- a/extension/lib/wallet/query.ts
+++ b/extension/lib/wallet/query.ts
@@ -288,6 +288,29 @@ class QueryRoot {
}
/**
+ * Get one object from a store by its key.
+ */
+ getIndexed(storeName, indexName, key): Promise<any> {
+ if (key === void 0) {
+ throw Error("key must not be undefined");
+ }
+
+ const {resolve, promise} = openPromise();
+
+ const doGetIndexed = (tx) => {
+ const req = tx.objectStore(storeName).index(indexName).get(key);
+ req.onsuccess = (r) => {
+ resolve(req.result);
+ };
+ };
+
+ this.addWork(doGetIndexed, storeName, false);
+ return Promise.resolve()
+ .then(() => this.finish())
+ .then(() => promise);
+ }
+
+ /**
* Finish the query, and start the query in the first place if necessary.
*/
finish(): Promise<void> {
diff --git a/extension/lib/wallet/types.ts b/extension/lib/wallet/types.ts
index 88b55f918..9c7b21b7c 100644
--- a/extension/lib/wallet/types.ts
+++ b/extension/lib/wallet/types.ts
@@ -257,6 +257,13 @@ export namespace Amounts {
}
+export interface CheckRepurchaseResult {
+ isRepurchase: boolean;
+ existingContractHash?: string;
+ existingFulfillmentUrl?: string;
+}
+
+
export interface Notifier {
notify();
} \ No newline at end of file
diff --git a/extension/lib/wallet/wallet.ts b/extension/lib/wallet/wallet.ts
index 67e35bd11..92fb92a4a 100644
--- a/extension/lib/wallet/wallet.ts
+++ b/extension/lib/wallet/wallet.ts
@@ -32,6 +32,7 @@ import {Reserve} from "./types";
import {CryptoApi} from "./cryptoApi";
import {Coin} from "./types";
import {PayCoinInfo} from "./types";
+import {CheckRepurchaseResult} from "./types";
"use strict";
@@ -279,8 +280,9 @@ interface CoinPaySig {
interface Transaction {
contractHash: string;
- contract: any;
+ contract: Contract;
payReq: any;
+ merchantSig: string;
}
@@ -512,6 +514,7 @@ export class Wallet {
contractHash: offer.H_contract,
contract: offer.contract,
payReq: payReq,
+ merchantSig: offer.merchant_sig,
};
console.log("pay request");
@@ -926,4 +929,29 @@ export class Wallet {
.iter("history", {indexName: "timestamp"})
.reduce(collect, [])
}
+
+ checkRepurchase(contract: Contract): Promise<CheckRepurchaseResult> {
+ if (!contract.repurchase_correlation_id) {
+ console.log("no repurchase: no correlation id");
+ return Promise.resolve({isRepurchase: false});
+ }
+ return Query(this.db)
+ .getIndexed("transactions",
+ "repurchase",
+ [contract.merchant_pub, contract.repurchase_correlation_id])
+ .then((result: Transaction) => {
+ console.log("db result", result);
+ let isRepurchase;
+ if (result) {
+ console.assert(result.contract.repurchase_correlation_id == contract.repurchase_correlation_id);
+ return {
+ isRepurchase: true,
+ existingContractHash: result.contractHash,
+ existingFulfillmentUrl: result.contract.fulfillment_url,
+ };
+ } else {
+ return {isRepurchase: false};
+ }
+ });
+ }
} \ No newline at end of file
diff --git a/extension/lib/wallet/wxMessaging.ts b/extension/lib/wallet/wxMessaging.ts
index d497e5246..740873d88 100644
--- a/extension/lib/wallet/wxMessaging.ts
+++ b/extension/lib/wallet/wxMessaging.ts
@@ -22,6 +22,7 @@ import {Checkable} from "./checkable";
import {AmountJson} from "./types";
import Port = chrome.runtime.Port;
import {Notifier} from "./types";
+import {Contract} from "./wallet";
"use strict";
@@ -108,6 +109,10 @@ function makeHandlers(db: IDBDatabase,
let amount = AmountJson.checked(detail.amount);
return wallet.getReserveCreationInfo(detail.baseUrl, amount);
},
+ ["check-repurchase"]: function(detail) {
+ let contract = Contract.checked(detail.contract);
+ return wallet.checkRepurchase(contract);
+ },
["get-history"]: function(detail) {
// TODO: limit history length
return wallet.getHistory();