Leave sending the payment blob to the merchant.

This commit is contained in:
Florian Dold 2016-04-06 02:06:57 +02:00
parent 3877ace7dd
commit d5fc7ee42d
6 changed files with 90 additions and 75 deletions

View File

@ -90,6 +90,7 @@ namespace TalerNotify {
callback_url: URI(e.detail.callback_url) callback_url: URI(e.detail.callback_url)
.absoluteTo(document.location.href), .absoluteTo(document.location.href),
bank_url: document.location.href, bank_url: document.location.href,
wt_types: JSON.stringify(e.detail.wt_types),
}; };
let uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html")); let uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
document.location.href = uri.query(params).href(); document.location.href = uri.query(params).href();
@ -157,20 +158,17 @@ namespace TalerNotify {
}); });
}); });
// Should be: taler-request-payment, taler-result-payment
addHandler('taler-execute-payment', function(e: CustomEvent) { addHandler("taler-execute-contract", function(e: CustomEvent) {
console.log("got taler-execute-payment in content page"); console.log("got taler-execute-contract in content page");
if (!e.detail.pay_url) {
console.log("field 'pay_url' missing in taler-execute-payment event");
return;
}
const payUrl = e.detail.pay_url;
const msg = { const msg = {
type: "execute-payment", type: "execute-payment",
detail: { detail: {
H_contract: e.detail.H_contract, H_contract: e.detail.H_contract,
}, },
}; };
chrome.runtime.sendMessage(msg, (resp) => { chrome.runtime.sendMessage(msg, (resp) => {
console.log("got resp"); console.log("got resp");
console.dir(resp); console.dir(resp);
@ -190,25 +188,13 @@ namespace TalerNotify {
throw Error("contract missing"); throw Error("contract missing");
} }
console.log("Making request to ", payUrl); let evt = new CustomEvent("taler-notify-payment", {
let r = new XMLHttpRequest(); detail: {
r.open('post', payUrl); contract: resp.contract,
r.send(JSON.stringify(resp.payReq)); payment: resp.payReq,
r.onload = () => {
switch (r.status) {
case 200:
console.log("going to", contract.fulfillment_url);
// TODO: Is this the right thing? Does the reload
// TODO: override setting location.href?
window.location.href = subst(contract.fulfillment_url,
e.detail.H_contract);
window.location.reload(true);
break;
default:
console.log("Unexpected status code for $pay_url:", r.status);
break;
} }
}; });
document.dispatchEvent(evt);
}); });
}); });
} }

View File

@ -103,8 +103,13 @@ export interface IExchangeInfo {
denoms: Denomination[]; denoms: Denomination[];
} }
export interface WireInfo {
[type: string]: any;
}
export interface ReserveCreationInfo { export interface ReserveCreationInfo {
exchangeInfo: IExchangeInfo; exchangeInfo: IExchangeInfo;
wireInfo: WireInfo;
selectedDenoms: Denomination[]; selectedDenoms: Denomination[];
withdrawFee: AmountJson; withdrawFee: AmountJson;
overhead: AmountJson; overhead: AmountJson;

View File

@ -21,7 +21,7 @@
* @author Florian Dold * @author Florian Dold
*/ */
import {AmountJson, CreateReserveResponse, IExchangeInfo, Denomination, Notifier} from "./types"; import {AmountJson, CreateReserveResponse, IExchangeInfo, Denomination, Notifier, WireInfo} from "./types";
import {HttpResponse, RequestException} from "./http"; import {HttpResponse, RequestException} from "./http";
import {Query} from "./query"; import {Query} from "./query";
import {Checkable} from "./checkable"; import {Checkable} from "./checkable";
@ -184,7 +184,6 @@ export class ConfirmReserveRequest {
} }
@Checkable.Class @Checkable.Class
export class Offer { export class Offer {
@Checkable.Value(Contract) @Checkable.Value(Contract)
@ -346,12 +345,15 @@ export class Wallet {
* but only if the sum the coins' remaining value exceeds the payment amount. * but only if the sum the coins' remaining value exceeds the payment amount.
*/ */
private getPossibleExchangeCoins(paymentAmount: AmountJson, private getPossibleExchangeCoins(paymentAmount: AmountJson,
depositFeeLimit: AmountJson, depositFeeLimit: AmountJson,
allowedExchanges: ExchangeHandle[]): Promise<ExchangeCoins> { allowedExchanges: ExchangeHandle[]): Promise<ExchangeCoins> {
// Mapping from exchange base URL to list of coins together with their // Mapping from exchange base URL to list of coins together with their
// denomination // denomination
let m: ExchangeCoins = {}; let m: ExchangeCoins = {};
let x: number
function storeExchangeCoin(mc, url) { function storeExchangeCoin(mc, url) {
let exchange: IExchangeInfo = mc[0]; let exchange: IExchangeInfo = mc[0];
console.log("got coin for exchange", url); console.log("got coin for exchange", url);
@ -501,8 +503,8 @@ export class Wallet {
console.log("executing confirmPay"); console.log("executing confirmPay");
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
return this.getPossibleExchangeCoins(offer.contract.amount, return this.getPossibleExchangeCoins(offer.contract.amount,
offer.contract.max_fee, offer.contract.max_fee,
offer.contract.exchanges) offer.contract.exchanges)
}).then((mcs) => { }).then((mcs) => {
if (Object.keys(mcs).length == 0) { if (Object.keys(mcs).length == 0) {
console.log("not confirming payment, insufficient coins"); console.log("not confirming payment, insufficient coins");
@ -746,7 +748,8 @@ export class Wallet {
* Update the information about a reserve that is stored in the wallet * Update the information about a reserve that is stored in the wallet
* by quering the reserve's exchange. * by quering the reserve's exchange.
*/ */
private updateReserve(reservePub: string, exchange: ExchangeInfo): Promise<Reserve> { private updateReserve(reservePub: string,
exchange: ExchangeInfo): Promise<Reserve> {
return Query(this.db) return Query(this.db)
.get("reserves", reservePub) .get("reserves", reservePub)
.then((reserve) => { .then((reserve) => {
@ -781,29 +784,47 @@ export class Wallet {
} }
getWireInfo(baseUrl: string): Promise<WireInfo> {
baseUrl = canonicalizeBaseUrl(baseUrl);
let reqUrl = URI("wire").absoluteTo(baseUrl);
return this.http.get(reqUrl).then((resp: HttpResponse) => {
if (resp.status != 200) {
throw Error("/wire request failed");
}
let wiJson = JSON.parse(resp.responseText);
if (!wiJson) {
throw Error("/wire response malformed")
}
return wiJson;
});
}
getReserveCreationInfo(baseUrl: string, getReserveCreationInfo(baseUrl: string,
amount: AmountJson): Promise<ReserveCreationInfo> { amount: AmountJson): Promise<ReserveCreationInfo> {
return this.updateExchangeFromUrl(baseUrl) let p = this.updateExchangeFromUrl(baseUrl);
.then((exchangeInfo: IExchangeInfo) => { return p.then((exchangeInfo: IExchangeInfo) => {
let selectedDenoms = getWithdrawDenomList(amount, let selectedDenoms = getWithdrawDenomList(amount, exchangeInfo.denoms);
exchangeInfo.denoms); let acc = Amounts.getZero(amount.currency);
for (let d of selectedDenoms) {
acc = Amounts.add(acc, d.fee_withdraw).amount;
}
let actualCoinCost = selectedDenoms
.map((d: Denomination) => Amounts.add(d.value,
d.fee_withdraw).amount)
.reduce((a, b) => Amounts.add(a, b).amount);
return this.getWireInfo(baseUrl).then((wireInfo) => {
let ret: ReserveCreationInfo = {
exchangeInfo,
selectedDenoms,
wireInfo,
withdrawFee: acc,
overhead: Amounts.sub(amount, actualCoinCost).amount,
};
return ret;
});
let acc = Amounts.getZero(amount.currency); });
for (let d of selectedDenoms) {
acc = Amounts.add(acc, d.fee_withdraw).amount;
}
let actualCoinCost = selectedDenoms
.map((d: Denomination) => Amounts.add(d.value,
d.fee_withdraw).amount)
.reduce((a, b) => Amounts.add(a, b).amount);
let ret: ReserveCreationInfo = {
exchangeInfo,
selectedDenoms,
withdrawFee: acc,
overhead: Amounts.sub(amount, actualCoinCost).amount,
};
return ret;
});
} }
@ -834,12 +855,12 @@ export class Wallet {
} }
return exchangeInfo.mergeKeys(exchangeKeysJson, this.cryptoApi) return exchangeInfo.mergeKeys(exchangeKeysJson, this.cryptoApi)
.then(() => { .then(() => {
return Query(this.db) return Query(this.db)
.put("exchanges", exchangeInfo) .put("exchanges", exchangeInfo)
.finish() .finish()
.then(() => exchangeInfo); .then(() => exchangeInfo);
}); });
}); });
}); });

View File

@ -74,12 +74,17 @@ class Controller {
private request: XMLHttpRequest; private request: XMLHttpRequest;
amount: AmountJson; amount: AmountJson;
callbackUrl: string; callbackUrl: string;
wtTypes: string[];
detailCollapsed = m.prop<boolean>(true); detailCollapsed = m.prop<boolean>(true);
constructor(initialExchangeUrl: string, amount: AmountJson, callbackUrl: string) { constructor(initialExchangeUrl: string,
amount: AmountJson,
callbackUrl: string,
wt_types: string[]) {
console.log("creating main controller"); console.log("creating main controller");
this.amount = amount; this.amount = amount;
this.callbackUrl = callbackUrl; this.callbackUrl = callbackUrl;
this.wtTypes = wt_types;
this.timer = new DelayTimer(800, () => this.update()); this.timer = new DelayTimer(800, () => this.update());
this.url(initialExchangeUrl); this.url(initialExchangeUrl);
this.update(); this.update();
@ -125,7 +130,6 @@ class Controller {
doUpdate(); doUpdate();
console.log("got update"); console.log("got update");
} }
@ -139,15 +143,21 @@ class Controller {
} }
} }
confirmReserve(exchange: string, amount: AmountJson, callback_url: string) { confirmReserve(rci: ReserveCreationInfo,
exchange: string,
amount: AmountJson,
callback_url: string) {
const d = {exchange, amount}; const d = {exchange, amount};
const cb = (rawResp) => { const cb = (rawResp) => {
if (!rawResp) { if (!rawResp) {
throw Error("empty response"); throw Error("empty response");
} }
// FIXME: filter out types that bank/exchange don't have in common
let wire_details = rci.wireInfo;
if (!rawResp.error) { if (!rawResp.error) {
const resp = CreateReserveResponse.checked(rawResp); const resp = CreateReserveResponse.checked(rawResp);
let q = { let q: {[name: string]: string|number} = {
wire_details: JSON.stringify(wire_details),
exchange: resp.exchange, exchange: resp.exchange,
reserve_pub: resp.reservePub, reserve_pub: resp.reservePub,
amount_value: amount.value, amount_value: amount.value,
@ -195,7 +205,8 @@ function view(ctrl: Controller) {
}); });
mx("button", { mx("button", {
onclick: () => ctrl.confirmReserve(ctrl.url(), onclick: () => ctrl.confirmReserve(ctrl.reserveCreationInfo,
ctrl.url(),
ctrl.amount, ctrl.amount,
ctrl.callbackUrl), ctrl.callbackUrl),
disabled: !ctrl.isValidExchange disabled: !ctrl.isValidExchange
@ -264,15 +275,6 @@ function renderReserveCreationDetails(rci: ReserveCreationInfo) {
} }
interface ExchangeProbeResult {
keyInfo?: any;
}
function probeExchange(exchangeBaseUrl: string): Promise<ExchangeProbeResult> {
throw Error("not implemented");
}
function getSuggestedExchange(currency: string): Promise<string> { function getSuggestedExchange(currency: string): Promise<string> {
// TODO: make this request go to the wallet backend // TODO: make this request go to the wallet backend
// Right now, this is a stub. // Right now, this is a stub.
@ -297,10 +299,11 @@ export function main() {
const amount = AmountJson.checked(JSON.parse(query.amount)); const amount = AmountJson.checked(JSON.parse(query.amount));
const callback_url = query.callback_url; const callback_url = query.callback_url;
const bank_url = query.bank_url; const bank_url = query.bank_url;
const wt_types = JSON.parse(query.wt_types);
getSuggestedExchange(amount.currency) getSuggestedExchange(amount.currency)
.then((suggestedExchangeUrl) => { .then((suggestedExchangeUrl) => {
const controller = () => new Controller(suggestedExchangeUrl, amount, callback_url); const controller = () => new Controller(suggestedExchangeUrl, amount, callback_url, wt_types);
var ExchangeSelection = {controller, view}; var ExchangeSelection = {controller, view};
m.mount(document.getElementById("exchange-selection"), ExchangeSelection); m.mount(document.getElementById("exchange-selection"), ExchangeSelection);
}) })

View File

@ -11,8 +11,8 @@
<script src="../lib/vendor/lodash.core.min.js"></script> <script src="../lib/vendor/lodash.core.min.js"></script>
<script src="../lib/vendor/system-csp-production.src.js"></script> <script src="../lib/vendor/system-csp-production.src.js"></script>
<script src="../lib/vendor/jed.js"></script> <script src="../lib/vendor/jed.js"></script>
<script src="../lib/i18n.js"></script>
<script src="../i18n/strings.js"></script> <script src="../i18n/strings.js"></script>
<script src="../lib/i18n.js"></script>
<script src="../lib/module-trampoline.js"></script> <script src="../lib/module-trampoline.js"></script>
</head> </head>

View File

@ -136,7 +136,7 @@ namespace WalletBalance {
{config: openInExtension}, {config: openInExtension},
i18n`help`); i18n`help`);
return i18n.parts`You have no balance to show. Need some ${helpLink}? getting started?`; return i18n.parts`You have no balance to show. Need some ${helpLink} getting started?`;
} }
} }