diff options
author | Florian Dold <florian.dold@gmail.com> | 2020-03-10 14:47:46 +0530 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2020-03-10 14:47:46 +0530 |
commit | 6e2881fabf74a3c1da8e94dcbe3e68fce6080d9e (patch) | |
tree | d0f9a5a03260ce0db057c3d962ca35947dffa26d /src/operations/recoup.ts | |
parent | 26d961ad633027f50ee402b9a7e7fa383c2b33c3 (diff) | |
download | wallet-core-6e2881fabf74a3c1da8e94dcbe3e68fce6080d9e.tar.xz |
cleanup
Diffstat (limited to 'src/operations/recoup.ts')
-rw-r--r-- | src/operations/recoup.ts | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/operations/recoup.ts b/src/operations/recoup.ts new file mode 100644 index 000000000..2b646a4d8 --- /dev/null +++ b/src/operations/recoup.ts @@ -0,0 +1,89 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU 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. + + GNU 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 + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * Imports. + */ +import { + Database +} from "../util/query"; +import { InternalWalletState } from "./state"; +import { Stores, TipRecord, CoinStatus } from "../types/dbTypes"; + +import { Logger } from "../util/logging"; +import { RecoupConfirmation, codecForRecoupConfirmation } from "../types/talerTypes"; +import { updateExchangeFromUrl } from "./exchanges"; +import { NotificationType } from "../types/notifications"; + +const logger = new Logger("payback.ts"); + +export async function recoup( + ws: InternalWalletState, + coinPub: string, +): Promise<void> { + let coin = await ws.db.get(Stores.coins, coinPub); + if (!coin) { + throw Error(`Coin ${coinPub} not found, can't request payback`); + } + const reservePub = coin.reservePub; + if (!reservePub) { + throw Error(`Can't request payback for a refreshed coin`); + } + const reserve = await ws.db.get(Stores.reserves, reservePub); + if (!reserve) { + throw Error(`Reserve of coin ${coinPub} not found`); + } + switch (coin.status) { + case CoinStatus.Dormant: + throw Error(`Can't do payback for coin ${coinPub} since it's dormant`); + } + coin.status = CoinStatus.Dormant; + // Even if we didn't get the payback yet, we suspend withdrawal, since + // technically we might update reserve status before we get the response + // from the reserve for the payback request. + reserve.hasPayback = true; + await ws.db.runWithWriteTransaction( + [Stores.coins, Stores.reserves], + async tx => { + await tx.put(Stores.coins, coin!!); + await tx.put(Stores.reserves, reserve); + }, + ); + ws.notify({ + type: NotificationType.PaybackStarted, + }); + + const paybackRequest = await ws.cryptoApi.createPaybackRequest(coin); + const reqUrl = new URL("payback", coin.exchangeBaseUrl); + const resp = await ws.http.postJson(reqUrl.href, paybackRequest); + if (resp.status !== 200) { + throw Error(); + } + const paybackConfirmation = codecForRecoupConfirmation().decode(await resp.json()); + if (paybackConfirmation.reserve_pub !== coin.reservePub) { + throw Error(`Coin's reserve doesn't match reserve on payback`); + } + coin = await ws.db.get(Stores.coins, coinPub); + if (!coin) { + throw Error(`Coin ${coinPub} not found, can't confirm payback`); + } + coin.status = CoinStatus.Dormant; + await ws.db.put(Stores.coins, coin); + ws.notify({ + type: NotificationType.PaybackFinished, + }); + await updateExchangeFromUrl(ws, coin.exchangeBaseUrl, true); +} |