simplify / fix transaction semantics

This commit is contained in:
Florian Dold 2016-10-19 22:59:24 +02:00
parent e6763f3fac
commit 6a11b512b3

View File

@ -749,9 +749,56 @@ export class Wallet {
private async processPreCoin(preCoin: PreCoin, private async processPreCoin(preCoin: PreCoin,
retryDelayMs = 100): Promise<void> { retryDelayMs = 100): Promise<void> {
let exchange = await this.q().get(Stores.exchanges,
preCoin.exchangeBaseUrl);
if (!exchange) {
console.error("db inconsistend: exchange for precoin not found");
return;
}
let denom = exchange.all_denoms.find((d) => d.denom_pub == preCoin.denomPub);
if (!denom) {
console.error("db inconsistent: denom for precoin not found");
return;
}
try { try {
const coin = await this.withdrawExecute(preCoin); const coin = await this.withdrawExecute(preCoin);
this.storeCoin(coin);
const mutateReserve = (r: ReserveRecord) => {
let currentAmount = r.current_amount;
if (!currentAmount) {
throw Error("can't withdraw from reserve when current amount is" +
" unknown");
}
let x = Amounts.sub(currentAmount,
preCoin.coinValue,
denom!.fee_withdraw);
if (x.saturated) {
throw AbortTransaction;
}
r.current_amount = x.amount;
return r;
};
let historyEntry: HistoryRecord = {
type: "withdraw",
timestamp: (new Date).getTime(),
level: HistoryLevel.Expert,
detail: {
coinPub: coin.coinPub,
}
};
await this.q()
.put(Stores.precoins, preCoin)
.mutate(Stores.reserves, preCoin.reservePub, mutateReserve)
.delete("precoins", coin.coinPub)
.add(Stores.coins, coin)
.add(Stores.history, historyEntry)
.finish();
this.notifier.notify();
} catch (e) { } catch (e) {
console.error("Failed to withdraw coin from precoin, retrying in", console.error("Failed to withdraw coin from precoin, retrying in",
retryDelayMs, retryDelayMs,
@ -889,60 +936,6 @@ export class Wallet {
return coin; return coin;
} }
async storeCoin(coin: Coin): Promise<void> {
let historyEntry: HistoryRecord = {
type: "withdraw",
timestamp: (new Date).getTime(),
level: HistoryLevel.Expert,
detail: {
coinPub: coin.coinPub,
}
};
await this.q()
.delete("precoins", coin.coinPub)
.add(Stores.coins, coin)
.add(Stores.history, historyEntry)
.finish();
this.notifier.notify();
}
/**
* Withdraw one coin of the given denomination from the given reserve.
*/
private async withdraw(denom: Denomination,
reserve: ReserveRecord): Promise<void> {
console.log("creating pre coin at", new Date());
let preCoin = await this.cryptoApi
.createPreCoin(denom, reserve);
let aborted = false;
function mutateReserve(r: ReserveRecord) {
let currentAmount = r.current_amount;
if (!currentAmount) {
throw Error("can't withdraw from reserve when current amount is" +
" unknown");
}
let x = Amounts.sub(currentAmount, preCoin.coinValue, denom.fee_withdraw);
if (x.saturated) {
aborted = true;
throw AbortTransaction;
}
r.current_amount = x.amount;
return r;
}
await this.q()
.put(Stores.precoins, preCoin)
.mutate(Stores.reserves, reserve.reserve_pub, mutateReserve)
.finish();
this.notifier.notify();
if (!aborted) {
await this.processPreCoin(preCoin);
}
}
/** /**
* Withdraw coins from a reserve until it is empty. * Withdraw coins from a reserve until it is empty.
@ -953,7 +946,11 @@ export class Wallet {
let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount, let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount,
denomsAvailable); denomsAvailable);
let ps = denomsForWithdraw.map((denom) => this.withdraw(denom, reserve)); let ps = denomsForWithdraw.map(async(denom) => {
let preCoin = await this.cryptoApi
.createPreCoin(denom, reserve);
await this.processPreCoin(preCoin);
});
await Promise.all(ps); await Promise.all(ps);
return ps.length; return ps.length;
} }