mint->exchange

This commit is contained in:
Florian Dold 2016-03-01 19:39:17 +01:00
parent 65eabbf6da
commit 9a197d619c
10 changed files with 123 additions and 124 deletions

View File

@ -45,7 +45,6 @@ var TalerNotify;
amount: JSON.stringify(e.detail.amount), amount: JSON.stringify(e.detail.amount),
callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href), callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href),
bank_url: document.location.href, bank_url: document.location.href,
suggested_mint: e.detail.suggested_mint,
}; };
var uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html")); var uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
document.location.href = uri.query(params).href(); document.location.href = uri.query(params).href();

View File

@ -8472,7 +8472,7 @@ function _TALER_WRALL_sign_deposit_permission($h_contract,$h_wire,$timestamp,$re
} }
return (0)|0; return (0)|0;
} }
function _TALER_WR_verify_confirmation($h_contract,$h_wire,$timestamp,$refund,$0,$1,$amount_minus_fee,$coin_pub,$merchant_pub,$sig,$mint_pub) { function _TALER_WR_verify_confirmation($h_contract,$h_wire,$timestamp,$refund,$0,$1,$amount_minus_fee,$coin_pub,$merchant_pub,$sig,$exchange_pub) {
$h_contract = $h_contract|0; $h_contract = $h_contract|0;
$h_wire = $h_wire|0; $h_wire = $h_wire|0;
$timestamp = $timestamp|0; $timestamp = $timestamp|0;
@ -8483,7 +8483,7 @@ function _TALER_WR_verify_confirmation($h_contract,$h_wire,$timestamp,$refund,$0
$coin_pub = $coin_pub|0; $coin_pub = $coin_pub|0;
$merchant_pub = $merchant_pub|0; $merchant_pub = $merchant_pub|0;
$sig = $sig|0; $sig = $sig|0;
$mint_pub = $mint_pub|0; $exchange_pub = $exchange_pub|0;
var $10 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $2 = 0, $20 = 0, $21 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0; var $10 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $2 = 0, $20 = 0, $21 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0;
var $29 = 0, $3 = 0, $30 = 0, $31 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $36 = 0, $37 = 0, $38 = 0, $39 = 0, $4 = 0, $40 = 0, $41 = 0, $42 = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0; var $29 = 0, $3 = 0, $30 = 0, $31 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $36 = 0, $37 = 0, $38 = 0, $39 = 0, $4 = 0, $40 = 0, $41 = 0, $42 = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0;
var $47 = 0, $48 = 0, $49 = 0, $5 = 0, $50 = 0, $51 = 0, $52 = 0, $53 = 0, $54 = 0, $55 = 0, $56 = 0, $57 = 0, $58 = 0, $59 = 0, $6 = 0, $60 = 0, $61 = 0, $62 = 0, $63 = 0, $64 = 0; var $47 = 0, $48 = 0, $49 = 0, $5 = 0, $50 = 0, $51 = 0, $52 = 0, $53 = 0, $54 = 0, $55 = 0, $56 = 0, $57 = 0, $58 = 0, $59 = 0, $6 = 0, $60 = 0, $61 = 0, $62 = 0, $63 = 0, $64 = 0;
@ -8514,7 +8514,7 @@ function _TALER_WR_verify_confirmation($h_contract,$h_wire,$timestamp,$refund,$0
$9 = $coin_pub; $9 = $coin_pub;
$10 = $merchant_pub; $10 = $merchant_pub;
$11 = $sig; $11 = $sig;
$12 = $mint_pub; $12 = $exchange_pub;
$19 = ((($dc)) + 8|0); $19 = ((($dc)) + 8|0);
$20 = $3; $20 = $3;
dest=$19; src=$20; stop=dest+64|0; do { HEAP8[dest>>0]=HEAP8[src>>0]|0; dest=dest+1|0; src=src+1|0; } while ((dest|0) < (stop|0)); dest=$19; src=$20; stop=dest+64|0; do { HEAP8[dest>>0]=HEAP8[src>>0]|0; dest=dest+1|0; src=src+1|0; } while ((dest|0) < (stop|0));

View File

@ -101,7 +101,7 @@ namespace RpcFunctions {
coinPub: coinPub.toCrock(), coinPub: coinPub.toCrock(),
coinPriv: coinPriv.toCrock(), coinPriv: coinPriv.toCrock(),
denomPub: denomPub.encode().toCrock(), denomPub: denomPub.encode().toCrock(),
mintBaseUrl: reserve.mint_base_url, exchangeBaseUrl: reserve.exchange_base_url,
withdrawSig: sig.toCrock(), withdrawSig: sig.toCrock(),
coinEv: ev.toCrock(), coinEv: ev.toCrock(),
coinValue: denom.value coinValue: denom.value

View File

@ -45,12 +45,12 @@ export function openTalerDb(): Promise<IDBDatabase> {
console.log("DB: upgrade needed: oldVersion = " + e.oldVersion); console.log("DB: upgrade needed: oldVersion = " + e.oldVersion);
switch (e.oldVersion) { switch (e.oldVersion) {
case 0: // DB does not exist yet case 0: // DB does not exist yet
const mints = db.createObjectStore("mints", {keyPath: "baseUrl"}); const exchanges = db.createObjectStore("exchanges", {keyPath: "baseUrl"});
mints.createIndex("pubKey", "masterPublicKey"); exchanges.createIndex("pubKey", "masterPublicKey");
db.createObjectStore("reserves", {keyPath: "reserve_pub"}); db.createObjectStore("reserves", {keyPath: "reserve_pub"});
db.createObjectStore("denoms", {keyPath: "denomPub"}); db.createObjectStore("denoms", {keyPath: "denomPub"});
const coins = db.createObjectStore("coins", {keyPath: "coinPub"}); const coins = db.createObjectStore("coins", {keyPath: "coinPub"});
coins.createIndex("mintBaseUrl", "mintBaseUrl"); coins.createIndex("exchangeBaseUrl", "exchangeBaseUrl");
const transactions = db.createObjectStore("transactions", const transactions = db.createObjectStore("transactions",
{keyPath: "contractHash"}); {keyPath: "contractHash"});
transactions.createIndex("repurchase", transactions.createIndex("repurchase",

View File

@ -36,7 +36,7 @@ export function amountToPretty(amount: AmountJson): string {
/** /**
* Canonicalize a base url, typically for the mint. * Canonicalize a base url, typically for the exchange.
* *
* See http://api.taler.net/wallet.html#general * See http://api.taler.net/wallet.html#general
*/ */
@ -62,4 +62,4 @@ export function parsePrettyAmount(pretty: string): AmountJson {
fraction: res[2] ? (parseFloat(`0.${res[2]}`) * 1e-6) : 0, fraction: res[2] ? (parseFloat(`0.${res[2]}`) * 1e-6) : 0,
currency: res[3] currency: res[3]
} }
} }

View File

@ -43,11 +43,11 @@ export class AmountJson {
@Checkable.Class @Checkable.Class
export class CreateReserveResponse { export class CreateReserveResponse {
/** /**
* Mint URL where the bank should create the reserve. * Exchange URL where the bank should create the reserve.
* The URL is canonicalized in the response. * The URL is canonicalized in the response.
*/ */
@Checkable.String @Checkable.String
mint: string; exchange: string;
@Checkable.String @Checkable.String
reservePub: string; reservePub: string;
@ -95,14 +95,14 @@ export class Denomination {
} }
export interface IMintInfo { export interface IExchangeInfo {
baseUrl: string; baseUrl: string;
masterPublicKey: string; masterPublicKey: string;
denoms: Denomination[]; denoms: Denomination[];
} }
export interface ReserveCreationInfo { export interface ReserveCreationInfo {
mintInfo: IMintInfo; exchangeInfo: IExchangeInfo;
selectedDenoms: Denomination[]; selectedDenoms: Denomination[];
withdrawFee: AmountJson; withdrawFee: AmountJson;
overhead: AmountJson; overhead: AmountJson;
@ -117,13 +117,13 @@ export interface PreCoin {
blindingKey: string; blindingKey: string;
withdrawSig: string; withdrawSig: string;
coinEv: string; coinEv: string;
mintBaseUrl: string; exchangeBaseUrl: string;
coinValue: AmountJson; coinValue: AmountJson;
} }
export interface Reserve { export interface Reserve {
mint_base_url: string exchange_base_url: string
reserve_priv: string; reserve_priv: string;
reserve_pub: string; reserve_pub: string;
} }
@ -144,7 +144,7 @@ export interface Coin {
denomPub: string; denomPub: string;
denomSig: string; denomSig: string;
currentAmount: AmountJson; currentAmount: AmountJson;
mintBaseUrl: string; exchangeBaseUrl: string;
} }
@ -266,4 +266,4 @@ export interface CheckRepurchaseResult {
export interface Notifier { export interface Notifier {
notify(); notify();
} }

View File

@ -21,7 +21,7 @@
* @author Florian Dold * @author Florian Dold
*/ */
import {AmountJson, CreateReserveResponse, IMintInfo, Denomination, Notifier} from "./types"; import {AmountJson, CreateReserveResponse, IExchangeInfo, Denomination, Notifier} 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";
@ -70,7 +70,7 @@ export class KeysJson {
} }
class MintInfo implements IMintInfo { class ExchangeInfo implements IExchangeInfo {
baseUrl: string; baseUrl: string;
masterPublicKey: string; masterPublicKey: string;
denoms: Denomination[]; denoms: Denomination[];
@ -89,15 +89,15 @@ class MintInfo implements IMintInfo {
} }
} }
static fresh(baseUrl: string): MintInfo { static fresh(baseUrl: string): ExchangeInfo {
return new MintInfo({baseUrl}); return new ExchangeInfo({baseUrl});
} }
/** /**
* Merge new key information into the mint info. * Merge new key information into the exchange info.
* If the new key information is invalid (missing fields, * If the new key information is invalid (missing fields,
* invalid signatures), an exception is thrown, but the * invalid signatures), an exception is thrown, but the
* mint info is updated with the new information up until * exchange info is updated with the new information up until
* the first error. * the first error.
*/ */
mergeKeys(newKeys: KeysJson, cryptoApi: CryptoApi): Promise<void> { mergeKeys(newKeys: KeysJson, cryptoApi: CryptoApi): Promise<void> {
@ -160,10 +160,10 @@ export class CreateReserveRequest {
amount: AmountJson; amount: AmountJson;
/** /**
* Mint URL where the bank should create the reserve. * Exchange URL where the bank should create the reserve.
*/ */
@Checkable.String @Checkable.String
mint: string; exchange: string;
static checked: (obj: any) => CreateReserveRequest; static checked: (obj: any) => CreateReserveRequest;
} }
@ -183,14 +183,14 @@ export class ConfirmReserveRequest {
@Checkable.Class @Checkable.Class
export class MintHandle { export class ExchangeHandle {
@Checkable.String @Checkable.String
master_pub: string; master_pub: string;
@Checkable.String @Checkable.String
url: string; url: string;
static checked: (obj: any) => MintHandle; static checked: (obj: any) => ExchangeHandle;
} }
@ -220,8 +220,8 @@ export class Contract {
@Checkable.String @Checkable.String
merchant_pub: string; merchant_pub: string;
@Checkable.List(Checkable.Value(MintHandle)) @Checkable.List(Checkable.Value(ExchangeHandle))
mints: MintHandle[]; exchanges: ExchangeHandle[];
@Checkable.List(Checkable.AnyObject) @Checkable.List(Checkable.AnyObject)
products: any[]; products: any[];
@ -264,8 +264,8 @@ interface ConfirmPayRequest {
offer: Offer; offer: Offer;
} }
interface MintCoins { interface ExchangeCoins {
[mintUrl: string]: CoinWithDenom[]; [exchangeUrl: string]: CoinWithDenom[];
} }
@ -402,22 +402,22 @@ export class Wallet {
/** /**
* Get mints and associated coins that are still spendable, * Get exchanges and associated coins that are still spendable,
* 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 getPossibleMintCoins(paymentAmount: AmountJson, private getPossibleExchangeCoins(paymentAmount: AmountJson,
depositFeeLimit: AmountJson, depositFeeLimit: AmountJson,
allowedMints: MintHandle[]): Promise<MintCoins> { allowedExchanges: ExchangeHandle[]): Promise<ExchangeCoins> {
// Mapping from mint 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: MintCoins = {}; let m: ExchangeCoins = {};
function storeMintCoin(mc) { function storeExchangeCoin(mc) {
let mint: IMintInfo = mc[0]; let exchange: IExchangeInfo = mc[0];
let coin: Coin = mc[1]; let coin: Coin = mc[1];
let cd = { let cd = {
coin: coin, coin: coin,
denom: mint.denoms.find((e) => e.denom_pub === coin.denomPub) denom: exchange.denoms.find((e) => e.denom_pub === coin.denomPub)
}; };
if (!cd.denom) { if (!cd.denom) {
throw Error("denom not found (database inconsistent)"); throw Error("denom not found (database inconsistent)");
@ -426,36 +426,36 @@ export class Wallet {
console.warn("same pubkey for different currencies"); console.warn("same pubkey for different currencies");
return; return;
} }
let x = m[mint.baseUrl]; let x = m[exchange.baseUrl];
if (!x) { if (!x) {
m[mint.baseUrl] = [cd]; m[exchange.baseUrl] = [cd];
} else { } else {
x.push(cd); x.push(cd);
} }
} }
let ps = allowedMints.map((info) => { let ps = allowedExchanges.map((info) => {
console.log("Checking for merchant's mint", JSON.stringify(info)); console.log("Checking for merchant's exchange", JSON.stringify(info));
return Query(this.db) return Query(this.db)
.iter("mints", {indexName: "pubKey", only: info.master_pub}) .iter("exchanges", {indexName: "pubKey", only: info.master_pub})
.indexJoin("coins", "mintBaseUrl", (mint) => mint.baseUrl) .indexJoin("coins", "exchangeBaseUrl", (exchange) => exchange.baseUrl)
.reduce(storeMintCoin); .reduce(storeExchangeCoin);
}); });
return Promise.all(ps).then(() => { return Promise.all(ps).then(() => {
let ret: MintCoins = {}; let ret: ExchangeCoins = {};
if (Object.keys(m).length == 0) { if (Object.keys(m).length == 0) {
console.log("not suitable mints found"); console.log("not suitable exchanges found");
} }
console.dir(m); console.dir(m);
// We try to find the first mint where we have // We try to find the first exchange where we have
// enough coins to cover the paymentAmount with fees // enough coins to cover the paymentAmount with fees
// under depositFeeLimit // under depositFeeLimit
nextMint: nextExchange:
for (let key in m) { for (let key in m) {
let coins = m[key]; let coins = m[key];
// Sort by ascending deposit fee // Sort by ascending deposit fee
@ -479,12 +479,12 @@ export class Wallet {
// FIXME: if the fees are too high, we have // FIXME: if the fees are too high, we have
// to cover them ourselves .... // to cover them ourselves ....
console.log("too much fees"); console.log("too much fees");
continue nextMint; continue nextExchange;
} }
usableCoins.push(coins[i]); usableCoins.push(coins[i]);
if (Amounts.cmp(accAmount, minAmount) >= 0) { if (Amounts.cmp(accAmount, minAmount) >= 0) {
ret[key] = usableCoins; ret[key] = usableCoins;
continue nextMint; continue nextExchange;
} }
} }
} }
@ -499,14 +499,14 @@ export class Wallet {
*/ */
private recordConfirmPay(offer: Offer, private recordConfirmPay(offer: Offer,
payCoinInfo: PayCoinInfo, payCoinInfo: PayCoinInfo,
chosenMint: string): Promise<void> { chosenExchange: string): Promise<void> {
let payReq = {}; let payReq = {};
payReq["amount"] = offer.contract.amount; payReq["amount"] = offer.contract.amount;
payReq["coins"] = payCoinInfo.map((x) => x.sig); payReq["coins"] = payCoinInfo.map((x) => x.sig);
payReq["H_contract"] = offer.H_contract; payReq["H_contract"] = offer.H_contract;
payReq["max_fee"] = offer.contract.max_fee; payReq["max_fee"] = offer.contract.max_fee;
payReq["merchant_sig"] = offer.merchant_sig; payReq["merchant_sig"] = offer.merchant_sig;
payReq["mint"] = URI(chosenMint).href(); payReq["exchange"] = URI(chosenExchange).href();
payReq["refund_deadline"] = offer.contract.refund_deadline; payReq["refund_deadline"] = offer.contract.refund_deadline;
payReq["timestamp"] = offer.contract.timestamp; payReq["timestamp"] = offer.contract.timestamp;
payReq["transaction_id"] = offer.contract.transaction_id; payReq["transaction_id"] = offer.contract.transaction_id;
@ -549,9 +549,9 @@ export class Wallet {
confirmPay(offer: Offer): Promise<any> { confirmPay(offer: Offer): Promise<any> {
console.log("executing confirmPay"); console.log("executing confirmPay");
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
return this.getPossibleMintCoins(offer.contract.amount, return this.getPossibleExchangeCoins(offer.contract.amount,
offer.contract.max_fee, offer.contract.max_fee,
offer.contract.mints) 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");
@ -559,10 +559,10 @@ export class Wallet {
error: "coins-insufficient", error: "coins-insufficient",
}; };
} }
let mintUrl = Object.keys(mcs)[0]; let exchangeUrl = Object.keys(mcs)[0];
return this.cryptoApi.signDeposit(offer, mcs[mintUrl]) return this.cryptoApi.signDeposit(offer, mcs[exchangeUrl])
.then((ds) => this.recordConfirmPay(offer, ds, mintUrl)) .then((ds) => this.recordConfirmPay(offer, ds, exchangeUrl))
.then(() => ({})); .then(() => ({}));
}); });
} }
@ -599,11 +599,11 @@ export class Wallet {
* then deplete the reserve, withdrawing coins until it is empty. * then deplete the reserve, withdrawing coins until it is empty.
*/ */
private initReserve(reserveRecord) { private initReserve(reserveRecord) {
this.updateMintFromUrl(reserveRecord.mint_base_url) this.updateExchangeFromUrl(reserveRecord.exchange_base_url)
.then((mint) => .then((exchange) =>
this.updateReserve(reserveRecord.reserve_pub, mint) this.updateReserve(reserveRecord.reserve_pub, exchange)
.then((reserve) => this.depleteReserve(reserve, .then((reserve) => this.depleteReserve(reserve,
mint))) exchange)))
.then(() => { .then(() => {
let depleted = { let depleted = {
type: "depleted-reserve", type: "depleted-reserve",
@ -627,12 +627,12 @@ export class Wallet {
createReserve(req: CreateReserveRequest): Promise<CreateReserveResponse> { createReserve(req: CreateReserveRequest): Promise<CreateReserveResponse> {
return this.cryptoApi.createEddsaKeypair().then((keypair) => { return this.cryptoApi.createEddsaKeypair().then((keypair) => {
const now = (new Date).getTime(); const now = (new Date).getTime();
const canonMint = canonicalizeBaseUrl(req.mint); const canonExchange = canonicalizeBaseUrl(req.exchange);
const reserveRecord = { const reserveRecord = {
reserve_pub: keypair.pub, reserve_pub: keypair.pub,
reserve_priv: keypair.priv, reserve_priv: keypair.priv,
mint_base_url: canonMint, exchange_base_url: canonExchange,
created: now, created: now,
last_query: null, last_query: null,
current_amount: null, current_amount: null,
@ -656,7 +656,7 @@ export class Wallet {
.finish() .finish()
.then(() => { .then(() => {
let r: CreateReserveResponse = { let r: CreateReserveResponse = {
mint: canonMint, exchange: canonExchange,
reservePub: keypair.pub, reservePub: keypair.pub,
}; };
return r; return r;
@ -668,7 +668,7 @@ export class Wallet {
/** /**
* Mark an existing reserve as confirmed. The wallet will start trying * Mark an existing reserve as confirmed. The wallet will start trying
* to withdraw from that reserve. This may not immediately succeed, * to withdraw from that reserve. This may not immediately succeed,
* since the mint might not know about the reserve yet, even though the * since the exchange might not know about the reserve yet, even though the
* bank confirmed its creation. * bank confirmed its creation.
* *
* A confirmed reserve should be shown to the user in the UI, while * A confirmed reserve should be shown to the user in the UI, while
@ -708,7 +708,7 @@ export class Wallet {
wd.reserve_pub = pc.reservePub; wd.reserve_pub = pc.reservePub;
wd.reserve_sig = pc.withdrawSig; wd.reserve_sig = pc.withdrawSig;
wd.coin_ev = pc.coinEv; wd.coin_ev = pc.coinEv;
let reqUrl = URI("reserve/withdraw").absoluteTo(r.mint_base_url); let reqUrl = URI("reserve/withdraw").absoluteTo(r.exchange_base_url);
return this.http.postJson(reqUrl, wd); return this.http.postJson(reqUrl, wd);
}) })
.then(resp => { .then(resp => {
@ -727,7 +727,7 @@ export class Wallet {
denomPub: pc.denomPub, denomPub: pc.denomPub,
denomSig: denomSig, denomSig: denomSig,
currentAmount: pc.coinValue, currentAmount: pc.coinValue,
mintBaseUrl: pc.mintBaseUrl, exchangeBaseUrl: pc.exchangeBaseUrl,
}; };
return coin; return coin;
@ -775,8 +775,8 @@ export class Wallet {
/** /**
* Withdraw coins from a reserve until it is empty. * Withdraw coins from a reserve until it is empty.
*/ */
private depleteReserve(reserve, mint: MintInfo): Promise<void> { private depleteReserve(reserve, exchange: ExchangeInfo): Promise<void> {
let denomsAvailable: Denomination[] = copy(mint.denoms); let denomsAvailable: Denomination[] = copy(exchange.denoms);
let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount, let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount,
denomsAvailable); denomsAvailable);
@ -793,13 +793,13 @@ 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 mint. * by quering the reserve's exchange.
*/ */
private updateReserve(reservePub: string, mint: MintInfo): 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) => {
let reqUrl = URI("reserve/status").absoluteTo(mint.baseUrl); let reqUrl = URI("reserve/status").absoluteTo(exchange.baseUrl);
reqUrl.query({'reserve_pub': reservePub}); reqUrl.query({'reserve_pub': reservePub});
return this.http.get(reqUrl).then(resp => { return this.http.get(reqUrl).then(resp => {
if (resp.status != 200) { if (resp.status != 200) {
@ -832,10 +832,10 @@ export class Wallet {
getReserveCreationInfo(baseUrl: string, getReserveCreationInfo(baseUrl: string,
amount: AmountJson): Promise<ReserveCreationInfo> { amount: AmountJson): Promise<ReserveCreationInfo> {
return this.updateMintFromUrl(baseUrl) return this.updateExchangeFromUrl(baseUrl)
.then((mintInfo: IMintInfo) => { .then((exchangeInfo: IExchangeInfo) => {
let selectedDenoms = getWithdrawDenomList(amount, let selectedDenoms = getWithdrawDenomList(amount,
mintInfo.denoms); exchangeInfo.denoms);
let acc = Amounts.getZero(amount.currency); let acc = Amounts.getZero(amount.currency);
for (let d of selectedDenoms) { for (let d of selectedDenoms) {
@ -846,7 +846,7 @@ export class Wallet {
d.fee_withdraw).amount) d.fee_withdraw).amount)
.reduce((a, b) => Amounts.add(a, b).amount); .reduce((a, b) => Amounts.add(a, b).amount);
let ret: ReserveCreationInfo = { let ret: ReserveCreationInfo = {
mintInfo, exchangeInfo,
selectedDenoms, selectedDenoms,
withdrawFee: acc, withdrawFee: acc,
overhead: Amounts.sub(amount, actualCoinCost).amount, overhead: Amounts.sub(amount, actualCoinCost).amount,
@ -857,37 +857,37 @@ export class Wallet {
/** /**
* Update or add mint DB entry by fetching the /keys information. * Update or add exchange DB entry by fetching the /keys information.
* Optionally link the reserve entry to the new or existing * Optionally link the reserve entry to the new or existing
* mint entry in then DB. * exchange entry in then DB.
*/ */
updateMintFromUrl(baseUrl): Promise<MintInfo> { updateExchangeFromUrl(baseUrl): Promise<ExchangeInfo> {
baseUrl = canonicalizeBaseUrl(baseUrl); baseUrl = canonicalizeBaseUrl(baseUrl);
let reqUrl = URI("keys").absoluteTo(baseUrl); let reqUrl = URI("keys").absoluteTo(baseUrl);
return this.http.get(reqUrl).then((resp) => { return this.http.get(reqUrl).then((resp) => {
if (resp.status != 200) { if (resp.status != 200) {
throw Error("/keys request failed"); throw Error("/keys request failed");
} }
let mintKeysJson = KeysJson.checked(JSON.parse(resp.responseText)); let exchangeKeysJson = KeysJson.checked(JSON.parse(resp.responseText));
return Query(this.db).get("mints", baseUrl).then((r) => { return Query(this.db).get("exchanges", baseUrl).then((r) => {
let mintInfo; let exchangeInfo;
console.dir(r); console.dir(r);
if (!r) { if (!r) {
mintInfo = MintInfo.fresh(baseUrl); exchangeInfo = ExchangeInfo.fresh(baseUrl);
console.log("making fresh mint"); console.log("making fresh exchange");
} else { } else {
mintInfo = new MintInfo(r); exchangeInfo = new ExchangeInfo(r);
console.log("using old mint"); console.log("using old exchange");
} }
return mintInfo.mergeKeys(mintKeysJson, this.cryptoApi) return exchangeInfo.mergeKeys(exchangeKeysJson, this.cryptoApi)
.then(() => { .then(() => {
return Query(this.db) return Query(this.db)
.put("mints", mintInfo) .put("exchanges", exchangeInfo)
.finish() .finish()
.then(() => mintInfo); .then(() => exchangeInfo);
}); });
}); });
@ -954,4 +954,4 @@ export class Wallet {
} }
}); });
} }
} }

View File

@ -60,7 +60,7 @@ function makeHandlers(db: IDBDatabase,
}, },
["create-reserve"]: function(detail) { ["create-reserve"]: function(detail) {
const d = { const d = {
mint: detail.mint, exchange: detail.exchange,
amount: detail.amount, amount: detail.amount,
}; };
const req = CreateReserveRequest.checked(d); const req = CreateReserveRequest.checked(d);
@ -96,11 +96,11 @@ function makeHandlers(db: IDBDatabase,
["execute-payment"]: function(detail) { ["execute-payment"]: function(detail) {
return wallet.executePayment(detail.H_contract); return wallet.executePayment(detail.H_contract);
}, },
["mint-info"]: function(detail) { ["exchange-info"]: function(detail) {
if (!detail.baseUrl) { if (!detail.baseUrl) {
return Promise.resolve({error: "bad url"}); return Promise.resolve({error: "bad url"});
} }
return wallet.updateMintFromUrl(detail.baseUrl); return wallet.updateExchangeFromUrl(detail.baseUrl);
}, },
["reserve-creation-info"]: function(detail) { ["reserve-creation-info"]: function(detail) {
if (!detail.baseUrl || typeof detail.baseUrl !== "string") { if (!detail.baseUrl || typeof detail.baseUrl !== "string") {

View File

@ -28,7 +28,7 @@
<section id="main"> <section id="main">
<article> <article>
<div class="fade" id="mint-selection"></div> <div class="fade" id="exchange-selection"></div>
</article> </article>
</section> </section>
</body> </body>

View File

@ -19,7 +19,7 @@
import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers"; import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers";
import {AmountJson, CreateReserveResponse} from "../lib/wallet/types"; import {AmountJson, CreateReserveResponse} from "../lib/wallet/types";
import m from "mithril"; import m from "mithril";
import {IMintInfo} from "../lib/wallet/types"; import {IExchangeInfo} from "../lib/wallet/types";
import {ReserveCreationInfo, Amounts} from "../lib/wallet/types"; import {ReserveCreationInfo, Amounts} from "../lib/wallet/types";
import MithrilComponent = _mithril.MithrilComponent; import MithrilComponent = _mithril.MithrilComponent;
import {Denomination} from "../lib/wallet/types"; import {Denomination} from "../lib/wallet/types";
@ -60,7 +60,7 @@ class DelayTimer {
class Controller { class Controller {
url = m.prop<string>(); url = m.prop<string>();
statusString = null; statusString = null;
isValidMint = false; isValidExchange = false;
reserveCreationInfo: ReserveCreationInfo = null; reserveCreationInfo: ReserveCreationInfo = null;
private timer: DelayTimer; private timer: DelayTimer;
private request: XMLHttpRequest; private request: XMLHttpRequest;
@ -68,12 +68,12 @@ class Controller {
callbackUrl: string; callbackUrl: string;
detailCollapsed = m.prop<boolean>(true); detailCollapsed = m.prop<boolean>(true);
constructor(initialMintUrl: string, amount: AmountJson, callbackUrl: string) { constructor(initialExchangeUrl: string, amount: AmountJson, callbackUrl: string) {
console.log("creating main controller"); console.log("creating main controller");
this.amount = amount; this.amount = amount;
this.callbackUrl = callbackUrl; this.callbackUrl = callbackUrl;
this.timer = new DelayTimer(800, () => this.update()); this.timer = new DelayTimer(800, () => this.update());
this.url(initialMintUrl); this.url(initialExchangeUrl);
this.update(); this.update();
} }
@ -93,19 +93,19 @@ class Controller {
m.redraw(true); m.redraw(true);
console.log("doing get mint info"); console.log("doing get exchange info");
getReserveCreationInfo(this.url(), this.amount) getReserveCreationInfo(this.url(), this.amount)
.then((r: ReserveCreationInfo) => { .then((r: ReserveCreationInfo) => {
console.log("get mint info resolved"); console.log("get exchange info resolved");
this.isValidMint = true; this.isValidExchange = true;
this.reserveCreationInfo = r; this.reserveCreationInfo = r;
console.dir(r); console.dir(r);
this.statusString = "The mint base URL is valid!"; this.statusString = "The exchange base URL is valid!";
m.endComputation(); m.endComputation();
}) })
.catch((e) => { .catch((e) => {
console.log("get mint info rejected"); console.log("get exchange info rejected");
if (e.hasOwnProperty("httpStatus")) { if (e.hasOwnProperty("httpStatus")) {
this.statusString = `request failed with status ${this.request.status}`; this.statusString = `request failed with status ${this.request.status}`;
} else { } else {
@ -122,7 +122,7 @@ class Controller {
} }
reset() { reset() {
this.isValidMint = false; this.isValidExchange = false;
this.statusString = null; this.statusString = null;
this.reserveCreationInfo = null; this.reserveCreationInfo = null;
if (this.request) { if (this.request) {
@ -131,8 +131,8 @@ class Controller {
} }
} }
confirmReserve(mint: string, amount: AmountJson, callback_url: string) { confirmReserve(exchange: string, amount: AmountJson, callback_url: string) {
const d = {mint, amount}; const d = {exchange, amount};
const cb = (rawResp) => { const cb = (rawResp) => {
if (!rawResp) { if (!rawResp) {
throw Error("empty response"); throw Error("empty response");
@ -140,7 +140,7 @@ class Controller {
if (!rawResp.error) { if (!rawResp.error) {
const resp = CreateReserveResponse.checked(rawResp); const resp = CreateReserveResponse.checked(rawResp);
let q = { let q = {
mint: resp.mint, exchange: resp.exchange,
reserve_pub: resp.reservePub, reserve_pub: resp.reservePub,
amount_value: amount.value, amount_value: amount.value,
amount_fraction: amount.fraction, amount_fraction: amount.fraction,
@ -190,7 +190,7 @@ function view(ctrl: Controller) {
onclick: () => ctrl.confirmReserve(ctrl.url(), onclick: () => ctrl.confirmReserve(ctrl.url(),
ctrl.amount, ctrl.amount,
ctrl.callbackUrl), ctrl.callbackUrl),
disabled: !ctrl.isValidMint disabled: !ctrl.isValidExchange
}, },
"Confirm exchange selection"); "Confirm exchange selection");
@ -256,30 +256,30 @@ function renderReserveCreationDetails(rci: ReserveCreationInfo) {
} }
interface MintProbeResult { interface ExchangeProbeResult {
keyInfo?: any; keyInfo?: any;
} }
function probeMint(mintBaseUrl: string): Promise<MintProbeResult> { function probeExchange(exchangeBaseUrl: string): Promise<ExchangeProbeResult> {
throw Error("not implemented"); throw Error("not implemented");
} }
function getSuggestedMint(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.
const defaultMint = { const defaultExchange = {
"KUDOS": "http://exchange.demo.taler.net", "KUDOS": "http://exchange.demo.taler.net",
"PUDOS": "http://exchange.test.taler.net", "PUDOS": "http://exchange.test.taler.net",
}; };
let mint = defaultMint[currency]; let exchange = defaultExchange[currency];
if (!mint) { if (!exchange) {
mint = "" exchange = ""
} }
return Promise.resolve(mint); return Promise.resolve(exchange);
} }
@ -290,11 +290,11 @@ export function main() {
const callback_url = query.callback_url; const callback_url = query.callback_url;
const bank_url = query.bank_url; const bank_url = query.bank_url;
getSuggestedMint(amount.currency) getSuggestedExchange(amount.currency)
.then((suggestedMintUrl) => { .then((suggestedExchangeUrl) => {
const controller = () => new Controller(suggestedMintUrl, amount, callback_url); const controller = () => new Controller(suggestedExchangeUrl, amount, callback_url);
var MintSelection = {controller, view}; var ExchangeSelection = {controller, view};
m.mount(document.getElementById("mint-selection"), MintSelection); m.mount(document.getElementById("exchange-selection"), ExchangeSelection);
}) })
.catch((e) => { .catch((e) => {
// TODO: provide more context information, maybe factor it out into a // TODO: provide more context information, maybe factor it out into a