aboutsummaryrefslogtreecommitdiff
path: root/src/operations
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-12-19 20:42:49 +0100
committerFlorian Dold <florian.dold@gmail.com>2019-12-19 20:42:49 +0100
commit0c9358c1b2bd80e25940022e86bd8daef8184ad7 (patch)
treea8c8ca0134bd886d8151633aff4c85e9513ad32c /src/operations
parent49e3b3e5b9bbf1ce356ef68f301d50c689ceecb9 (diff)
new date format, replace checkable annotations with codecs
Diffstat (limited to 'src/operations')
-rw-r--r--src/operations/exchanges.ts37
-rw-r--r--src/operations/history.ts15
-rw-r--r--src/operations/pay.ts212
-rw-r--r--src/operations/payback.ts4
-rw-r--r--src/operations/pending.ts10
-rw-r--r--src/operations/refresh.ts2
-rw-r--r--src/operations/refund.ts15
-rw-r--r--src/operations/reserves.ts9
-rw-r--r--src/operations/return.ts271
-rw-r--r--src/operations/tip.ts15
-rw-r--r--src/operations/withdraw.ts92
11 files changed, 208 insertions, 474 deletions
diff --git a/src/operations/exchanges.ts b/src/operations/exchanges.ts
index d9adc7c52..741be31ba 100644
--- a/src/operations/exchanges.ts
+++ b/src/operations/exchanges.ts
@@ -15,8 +15,8 @@
*/
import { InternalWalletState } from "./state";
-import { KeysJson, Denomination, ExchangeWireJson } from "../types/talerTypes";
-import { getTimestampNow, OperationError } from "../types/walletTypes";
+import { ExchangeKeysJson, Denomination, ExchangeWireJson, codecForExchangeKeysJson, codecForExchangeWireJson } from "../types/talerTypes";
+import { OperationError } from "../types/walletTypes";
import {
ExchangeRecord,
ExchangeUpdateStatus,
@@ -29,8 +29,6 @@ import {
} from "../types/dbTypes";
import {
canonicalizeBaseUrl,
- extractTalerStamp,
- extractTalerStampOrThrow,
} from "../util/helpers";
import { Database } from "../util/query";
import * as Amounts from "../util/amounts";
@@ -40,6 +38,7 @@ import {
guardOperationException,
} from "./errors";
import { WALLET_CACHE_BREAKER_CLIENT_VERSION } from "./versions";
+import { getTimestampNow } from "../util/time";
async function denominationRecordFromKeys(
ws: InternalWalletState,
@@ -57,12 +56,10 @@ async function denominationRecordFromKeys(
feeWithdraw: Amounts.parseOrThrow(denomIn.fee_withdraw),
isOffered: true,
masterSig: denomIn.master_sig,
- stampExpireDeposit: extractTalerStampOrThrow(denomIn.stamp_expire_deposit),
- stampExpireLegal: extractTalerStampOrThrow(denomIn.stamp_expire_legal),
- stampExpireWithdraw: extractTalerStampOrThrow(
- denomIn.stamp_expire_withdraw,
- ),
- stampStart: extractTalerStampOrThrow(denomIn.stamp_start),
+ stampExpireDeposit: denomIn.stamp_expire_deposit,
+ stampExpireLegal: denomIn.stamp_expire_legal,
+ stampExpireWithdraw: denomIn.stamp_expire_withdraw,
+ stampStart: denomIn.stamp_start,
status: DenominationStatus.Unverified,
value: Amounts.parseOrThrow(denomIn.value),
};
@@ -117,9 +114,9 @@ async function updateExchangeWithKeys(
});
throw new OperationFailedAndReportedError(m);
}
- let exchangeKeysJson: KeysJson;
+ let exchangeKeysJson: ExchangeKeysJson;
try {
- exchangeKeysJson = KeysJson.checked(keysResp);
+ exchangeKeysJson = codecForExchangeKeysJson().decode(keysResp);
} catch (e) {
const m = `Parsing /keys response failed: ${e.message}`;
await setExchangeError(ws, baseUrl, {
@@ -130,9 +127,7 @@ async function updateExchangeWithKeys(
throw new OperationFailedAndReportedError(m);
}
- const lastUpdateTimestamp = extractTalerStamp(
- exchangeKeysJson.list_issue_date,
- );
+ const lastUpdateTimestamp = exchangeKeysJson.list_issue_date
if (!lastUpdateTimestamp) {
const m = `Parsing /keys response failed: invalid list_issue_date.`;
await setExchangeError(ws, baseUrl, {
@@ -329,7 +324,7 @@ async function updateExchangeWithWireInfo(
if (!wiJson) {
throw Error("/wire response malformed");
}
- const wireInfo = ExchangeWireJson.checked(wiJson);
+ const wireInfo = codecForExchangeWireJson().decode(wiJson);
for (const a of wireInfo.accounts) {
console.log("validating exchange acct");
const isValid = await ws.cryptoApi.isValidWireAccount(
@@ -345,14 +340,8 @@ async function updateExchangeWithWireInfo(
for (const wireMethod of Object.keys(wireInfo.fees)) {
const feeList: WireFee[] = [];
for (const x of wireInfo.fees[wireMethod]) {
- const startStamp = extractTalerStamp(x.start_date);
- if (!startStamp) {
- throw Error("wrong date format");
- }
- const endStamp = extractTalerStamp(x.end_date);
- if (!endStamp) {
- throw Error("wrong date format");
- }
+ const startStamp = x.start_date;
+ const endStamp = x.end_date;
const fee: WireFee = {
closingFee: Amounts.parseOrThrow(x.closing_fee),
endStamp,
diff --git a/src/operations/history.ts b/src/operations/history.ts
index bb57a9c60..f02894b6b 100644
--- a/src/operations/history.ts
+++ b/src/operations/history.ts
@@ -37,6 +37,7 @@ import {
import { assertUnreachable } from "../util/assertUnreachable";
import { TransactionHandle, Store } from "../util/query";
import { ReserveTransactionType } from "../types/ReserveTransaction";
+import { timestampCmp } from "../util/time";
/**
* Create an event ID from the type and the primary key for the event.
@@ -53,11 +54,11 @@ function getOrderShortInfo(
return undefined;
}
return {
- amount: download.contractTerms.amount,
- orderId: download.contractTerms.order_id,
- merchantBaseUrl: download.contractTerms.merchant_base_url,
+ amount: Amounts.toString(download.contractData.amount),
+ orderId: download.contractData.orderId,
+ merchantBaseUrl: download.contractData.merchantBaseUrl,
proposalId: proposal.proposalId,
- summary: download.contractTerms.summary || "",
+ summary: download.contractData.summary,
};
}
@@ -356,9 +357,7 @@ export async function getHistory(
if (!orderShortInfo) {
return;
}
- const purchaseAmount = Amounts.parseOrThrow(
- purchase.contractTerms.amount,
- );
+ const purchaseAmount = purchase.contractData.amount;
let amountRefundedRaw = Amounts.getZero(purchaseAmount.currency);
let amountRefundedInvalid = Amounts.getZero(purchaseAmount.currency);
let amountRefundedEffective = Amounts.getZero(purchaseAmount.currency);
@@ -408,7 +407,7 @@ export async function getHistory(
},
);
- history.sort((h1, h2) => Math.sign(h1.timestamp.t_ms - h2.timestamp.t_ms));
+ history.sort((h1, h2) => timestampCmp(h1.timestamp, h2.timestamp));
return { history };
}
diff --git a/src/operations/pay.ts b/src/operations/pay.ts
index adbf6bb87..db2a24310 100644
--- a/src/operations/pay.ts
+++ b/src/operations/pay.ts
@@ -37,6 +37,7 @@ import {
Stores,
updateRetryInfoTimeout,
PayEventRecord,
+ WalletContractData,
} from "../types/dbTypes";
import { NotificationType } from "../types/notifications";
import {
@@ -46,33 +47,29 @@ import {
MerchantRefundResponse,
PayReq,
Proposal,
+ codecForMerchantRefundResponse,
+ codecForProposal,
+ codecForContractTerms,
} from "../types/talerTypes";
import {
CoinSelectionResult,
CoinWithDenom,
ConfirmPayResult,
- getTimestampNow,
OperationError,
PaySigInfo,
PreparePayResult,
RefreshReason,
- Timestamp,
} from "../types/walletTypes";
import * as Amounts from "../util/amounts";
import { AmountJson } from "../util/amounts";
-import {
- amountToPretty,
- canonicalJson,
- extractTalerDuration,
- extractTalerStampOrThrow,
- strcmp,
-} from "../util/helpers";
+import { amountToPretty, canonicalJson, strcmp } from "../util/helpers";
import { Logger } from "../util/logging";
import { getOrderDownloadUrl, parsePayUri } from "../util/taleruri";
import { guardOperationException } from "./errors";
import { createRefreshGroup, getTotalRefreshCost } from "./refresh";
import { acceptRefundResponse } from "./refund";
import { InternalWalletState } from "./state";
+import { Timestamp, getTimestampNow, timestampAddDuration } from "../util/time";
interface CoinsForPaymentArgs {
allowedAuditors: Auditor[];
@@ -177,20 +174,20 @@ export function selectPayCoins(
*/
async function getCoinsForPayment(
ws: InternalWalletState,
- args: CoinsForPaymentArgs,
+ args: WalletContractData,
): Promise<CoinSelectionResult | undefined> {
const {
allowedAuditors,
allowedExchanges,
- depositFeeLimit,
- paymentAmount,
+ maxDepositFee,
+ amount,
wireFeeAmortization,
- wireFeeLimit,
- wireFeeTime,
+ maxWireFee,
+ timestamp,
wireMethod,
} = args;
- let remainingAmount = paymentAmount;
+ let remainingAmount = amount;
const exchanges = await ws.db.iter(Stores.exchanges).toArray();
@@ -207,7 +204,7 @@ async function getCoinsForPayment(
// is the exchange explicitly allowed?
for (const allowedExchange of allowedExchanges) {
- if (allowedExchange.master_pub === exchangeDetails.masterPublicKey) {
+ if (allowedExchange.exchangePub === exchangeDetails.masterPublicKey) {
isOkay = true;
break;
}
@@ -217,7 +214,7 @@ async function getCoinsForPayment(
if (!isOkay) {
for (const allowedAuditor of allowedAuditors) {
for (const auditor of exchangeDetails.auditors) {
- if (auditor.auditor_pub === allowedAuditor.auditor_pub) {
+ if (auditor.auditor_pub === allowedAuditor.auditorPub) {
isOkay = true;
break;
}
@@ -281,7 +278,7 @@ async function getCoinsForPayment(
let totalFees = Amounts.getZero(currency);
let wireFee: AmountJson | undefined;
for (const fee of exchangeFees.feesForType[wireMethod] || []) {
- if (fee.startStamp <= wireFeeTime && fee.endStamp >= wireFeeTime) {
+ if (fee.startStamp <= timestamp && fee.endStamp >= timestamp) {
wireFee = fee.wireFee;
break;
}
@@ -289,13 +286,13 @@ async function getCoinsForPayment(
if (wireFee) {
const amortizedWireFee = Amounts.divide(wireFee, wireFeeAmortization);
- if (Amounts.cmp(wireFeeLimit, amortizedWireFee) < 0) {
+ if (Amounts.cmp(maxWireFee, amortizedWireFee) < 0) {
totalFees = Amounts.add(amortizedWireFee, totalFees).amount;
remainingAmount = Amounts.add(amortizedWireFee, remainingAmount).amount;
}
}
- const res = selectPayCoins(denoms, cds, remainingAmount, depositFeeLimit);
+ const res = selectPayCoins(denoms, cds, remainingAmount, maxDepositFee);
if (res) {
totalFees = Amounts.add(totalFees, res.totalFees).amount;
@@ -332,18 +329,17 @@ async function recordConfirmPay(
}
logger.trace(`recording payment with session ID ${sessionId}`);
const payReq: PayReq = {
- coins: payCoinInfo.coinInfo.map((x) => x.sig),
- merchant_pub: d.contractTerms.merchant_pub,
+ coins: payCoinInfo.coinInfo.map(x => x.sig),
+ merchant_pub: d.contractData.merchantPub,
mode: "pay",
- order_id: d.contractTerms.order_id,
+ order_id: d.contractData.orderId,
};
const t: PurchaseRecord = {
abortDone: false,
abortRequested: false,
- contractTerms: d.contractTerms,
- contractTermsHash: d.contractTermsHash,
+ contractTermsRaw: d.contractTermsRaw,
+ contractData: d.contractData,
lastSessionId: sessionId,
- merchantSig: d.merchantSig,
payReq,
timestampAccept: getTimestampNow(),
timestampLastRefundStatus: undefined,
@@ -383,14 +379,19 @@ async function recordConfirmPay(
throw Error("coin allocated for payment doesn't exist anymore");
}
coin.status = CoinStatus.Dormant;
- const remaining = Amounts.sub(coin.currentAmount, coinInfo.subtractedAmount);
+ const remaining = Amounts.sub(
+ coin.currentAmount,
+ coinInfo.subtractedAmount,
+ );
if (remaining.saturated) {
throw Error("not enough remaining balance on coin for payment");
}
coin.currentAmount = remaining.amount;
await tx.put(Stores.coins, coin);
}
- const refreshCoinPubs = payCoinInfo.coinInfo.map((x) => ({coinPub: x.coinPub}));
+ const refreshCoinPubs = payCoinInfo.coinInfo.map(x => ({
+ coinPub: x.coinPub,
+ }));
await createRefreshGroup(tx, refreshCoinPubs, RefreshReason.Pay);
},
);
@@ -402,11 +403,11 @@ async function recordConfirmPay(
return t;
}
-function getNextUrl(contractTerms: ContractTerms): string {
- const f = contractTerms.fulfillment_url;
+function getNextUrl(contractData: WalletContractData): string {
+ const f = contractData.fulfillmentUrl;
if (f.startsWith("http://") || f.startsWith("https://")) {
- const fu = new URL(contractTerms.fulfillment_url);
- fu.searchParams.set("order_id", contractTerms.order_id);
+ const fu = new URL(contractData.fulfillmentUrl);
+ fu.searchParams.set("order_id", contractData.orderId);
return fu.href;
} else {
return f;
@@ -440,7 +441,7 @@ export async function abortFailedPayment(
const abortReq = { ...purchase.payReq, mode: "abort-refund" };
- const payUrl = new URL("pay", purchase.contractTerms.merchant_base_url).href;
+ const payUrl = new URL("pay", purchase.contractData.merchantBaseUrl).href;
try {
resp = await ws.http.postJson(payUrl, abortReq);
@@ -454,7 +455,9 @@ export async function abortFailedPayment(
throw Error(`unexpected status for /pay (${resp.status})`);
}
- const refundResponse = MerchantRefundResponse.checked(await resp.json());
+ const refundResponse = codecForMerchantRefundResponse().decode(
+ await resp.json(),
+ );
await acceptRefundResponse(
ws,
purchase.proposalId,
@@ -574,13 +577,16 @@ async function processDownloadProposalImpl(
throw Error(`contract download failed with status ${resp.status}`);
}
- const proposalResp = Proposal.checked(await resp.json());
+ const proposalResp = codecForProposal().decode(await resp.json());
const contractTermsHash = await ws.cryptoApi.hashString(
canonicalJson(proposalResp.contract_terms),
);
- const fulfillmentUrl = proposalResp.contract_terms.fulfillment_url;
+ const parsedContractTerms = codecForContractTerms().decode(
+ proposalResp.contract_terms,
+ );
+ const fulfillmentUrl = parsedContractTerms.fulfillment_url;
await ws.db.runWithWriteTransaction(
[Stores.proposals, Stores.purchases],
@@ -592,10 +598,42 @@ async function processDownloadProposalImpl(
if (p.proposalStatus !== ProposalStatus.DOWNLOADING) {
return;
}
+ const amount = Amounts.parseOrThrow(parsedContractTerms.amount);
+ let maxWireFee: AmountJson;
+ if (parsedContractTerms.max_wire_fee) {
+ maxWireFee = Amounts.parseOrThrow(parsedContractTerms.max_wire_fee);
+ } else {
+ maxWireFee = Amounts.getZero(amount.currency);
+ }
p.download = {
- contractTerms: proposalResp.contract_terms,
- merchantSig: proposalResp.sig,
- contractTermsHash,
+ contractData: {
+ amount,
+ contractTermsHash: contractTermsHash,
+ fulfillmentUrl: parsedContractTerms.fulfillment_url,
+ merchantBaseUrl: parsedContractTerms.merchant_base_url,
+ merchantPub: parsedContractTerms.merchant_pub,
+ merchantSig: proposalResp.sig,
+ orderId: parsedContractTerms.order_id,
+ summary: parsedContractTerms.summary,
+ autoRefund: parsedContractTerms.auto_refund,
+ maxWireFee,
+ payDeadline: parsedContractTerms.pay_deadline,
+ refundDeadline: parsedContractTerms.refund_deadline,
+ wireFeeAmortization: parsedContractTerms.wire_fee_amortization || 1,
+ allowedAuditors: parsedContractTerms.auditors.map(x => ({
+ auditorBaseUrl: x.url,
+ auditorPub: x.master_pub,
+ })),
+ allowedExchanges: parsedContractTerms.exchanges.map(x => ({
+ exchangeBaseUrl: x.url,
+ exchangePub: x.master_pub,
+ })),
+ timestamp: parsedContractTerms.timestamp,
+ wireMethod: parsedContractTerms.wire_method,
+ wireInfoHash: parsedContractTerms.H_wire,
+ maxDepositFee: Amounts.parseOrThrow(parsedContractTerms.max_fee),
+ },
+ contractTermsRaw: JSON.stringify(proposalResp.contract_terms),
};
if (
fulfillmentUrl.startsWith("http://") ||
@@ -697,7 +735,7 @@ export async function submitPay(
console.log("paying with session ID", sessionId);
- const payUrl = new URL("pay", purchase.contractTerms.merchant_base_url).href;
+ const payUrl = new URL("pay", purchase.contractData.merchantBaseUrl).href;
try {
resp = await ws.http.postJson(payUrl, payReq);
@@ -714,10 +752,10 @@ export async function submitPay(
const now = getTimestampNow();
- const merchantPub = purchase.contractTerms.merchant_pub;
+ const merchantPub = purchase.contractData.merchantPub;
const valid: boolean = await ws.cryptoApi.isValidPaymentSignature(
merchantResp.sig,
- purchase.contractTermsHash,
+ purchase.contractData.contractTermsHash,
merchantPub,
);
if (!valid) {
@@ -731,19 +769,13 @@ export async function submitPay(
purchase.lastPayError = undefined;
purchase.payRetryInfo = initRetryInfo(false);
if (isFirst) {
- const ar = purchase.contractTerms.auto_refund;
+ const ar = purchase.contractData.autoRefund;
if (ar) {
console.log("auto_refund present");
- const autoRefundDelay = extractTalerDuration(ar);
- console.log("auto_refund valid", autoRefundDelay);
- if (autoRefundDelay) {
- purchase.refundStatusRequested = true;
- purchase.refundStatusRetryInfo = initRetryInfo();
- purchase.lastRefundStatusError = undefined;
- purchase.autoRefundDeadline = {
- t_ms: now.t_ms + autoRefundDelay.d_ms,
- };
- }
+ purchase.refundStatusRequested = true;
+ purchase.refundStatusRetryInfo = initRetryInfo();
+ purchase.lastRefundStatusError = undefined;
+ purchase.autoRefundDeadline = timestampAddDuration(now, ar);
}
}
@@ -761,8 +793,8 @@ export async function submitPay(
},
);
- const nextUrl = getNextUrl(purchase.contractTerms);
- ws.cachedNextUrl[purchase.contractTerms.fulfillment_url] = {
+ const nextUrl = getNextUrl(purchase.contractData);
+ ws.cachedNextUrl[purchase.contractData.fulfillmentUrl] = {
nextUrl,
lastSessionId: sessionId,
};
@@ -816,9 +848,9 @@ export async function preparePay(
console.error("bad proposal", proposal);
throw Error("proposal is in invalid state");
}
- const contractTerms = d.contractTerms;
- const merchantSig = d.merchantSig;
- if (!contractTerms || !merchantSig) {
+ const contractData = d.contractData;
+ const merchantSig = d.contractData.merchantSig;
+ if (!merchantSig) {
throw Error("BUG: proposal is in invalid state");
}
@@ -828,45 +860,31 @@ export async function preparePay(
const purchase = await ws.db.get(Stores.purchases, proposalId);
if (!purchase) {
- const paymentAmount = Amounts.parseOrThrow(contractTerms.amount);
- let wireFeeLimit;
- if (contractTerms.max_wire_fee) {
- wireFeeLimit = Amounts.parseOrThrow(contractTerms.max_wire_fee);
- } else {
- wireFeeLimit = Amounts.getZero(paymentAmount.currency);
- }
- // If not already payed, check if we could pay for it.
- const res = await getCoinsForPayment(ws, {
- allowedAuditors: contractTerms.auditors,
- allowedExchanges: contractTerms.exchanges,
- depositFeeLimit: Amounts.parseOrThrow(contractTerms.max_fee),
- paymentAmount,
- wireFeeAmortization: contractTerms.wire_fee_amortization || 1,
- wireFeeLimit,
- wireFeeTime: extractTalerStampOrThrow(contractTerms.timestamp),
- wireMethod: contractTerms.wire_method,
- });
+ // If not already paid, check if we could pay for it.
+ const res = await getCoinsForPayment(ws, contractData);
if (!res) {
console.log("not confirming payment, insufficient coins");
return {
status: "insufficient-balance",
- contractTerms: contractTerms,
+ contractTermsRaw: d.contractTermsRaw,
proposalId: proposal.proposalId,
};
}
return {
status: "payment-possible",
- contractTerms: contractTerms,
+ contractTermsRaw: d.contractTermsRaw,
proposalId: proposal.proposalId,
totalFees: res.totalFees,
};
}
if (uriResult.sessionId && purchase.lastSessionId !== uriResult.sessionId) {
- console.log("automatically re-submitting payment with different session ID")
- await ws.db.runWithWriteTransaction([Stores.purchases], async (tx) => {
+ console.log(
+ "automatically re-submitting payment with different session ID",
+ );
+ await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
const p = await tx.get(Stores.purchases, proposalId);
if (!p) {
return;
@@ -879,8 +897,8 @@ export async function preparePay(
return {
status: "paid",
- contractTerms: purchase.contractTerms,
- nextUrl: getNextUrl(purchase.contractTerms),
+ contractTermsRaw: purchase.contractTermsRaw,
+ nextUrl: getNextUrl(purchase.contractData),
};
}
@@ -906,7 +924,10 @@ export async function confirmPay(
throw Error("proposal is in invalid state");
}
- let purchase = await ws.db.get(Stores.purchases, d.contractTermsHash);
+ let purchase = await ws.db.get(
+ Stores.purchases,
+ d.contractData.contractTermsHash,
+ );
if (purchase) {
if (
@@ -926,25 +947,7 @@ export async function confirmPay(
logger.trace("confirmPay: purchase record does not exist yet");
- const contractAmount = Amounts.parseOrThrow(d.contractTerms.amount);
-
- let wireFeeLimit;
- if (!d.contractTerms.max_wire_fee) {
- wireFeeLimit = Amounts.getZero(contractAmount.currency);
- } else {
- wireFeeLimit = Amounts.parseOrThrow(d.contractTerms.max_wire_fee);
- }
-
- const res = await getCoinsForPayment(ws, {
- allowedAuditors: d.contractTerms.auditors,
- allowedExchanges: d.contractTerms.exchanges,
- depositFeeLimit: Amounts.parseOrThrow(d.contractTerms.max_fee),
- paymentAmount: Amounts.parseOrThrow(d.contractTerms.amount),
- wireFeeAmortization: d.contractTerms.wire_fee_amortization || 1,
- wireFeeLimit,
- wireFeeTime: extractTalerStampOrThrow(d.contractTerms.timestamp),
- wireMethod: d.contractTerms.wire_method,
- });
+ const res = await getCoinsForPayment(ws, d.contractData);
logger.trace("coin selection result", res);
@@ -956,7 +959,8 @@ export async function confirmPay(
const { cds, totalAmount } = res;
const payCoinInfo = await ws.cryptoApi.signDeposit(
- d.contractTerms,
+ d.contractTermsRaw,
+ d.contractData,
cds,
totalAmount,
);
@@ -964,7 +968,7 @@ export async function confirmPay(
ws,
proposal,
payCoinInfo,
- sessionIdOverride
+ sessionIdOverride,
);
logger.trace("confirmPay: submitting payment after creating purchase record");
diff --git a/src/operations/payback.ts b/src/operations/payback.ts
index 51adb6ad3..181527693 100644
--- a/src/operations/payback.ts
+++ b/src/operations/payback.ts
@@ -24,7 +24,7 @@ import { InternalWalletState } from "./state";
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
import { Logger } from "../util/logging";
-import { PaybackConfirmation } from "../types/talerTypes";
+import { RecoupConfirmation, codecForRecoupConfirmation } from "../types/talerTypes";
import { updateExchangeFromUrl } from "./exchanges";
import { NotificationType } from "../types/notifications";
@@ -72,7 +72,7 @@ export async function payback(
if (resp.status !== 200) {
throw Error();
}
- const paybackConfirmation = PaybackConfirmation.checked(await resp.json());
+ const paybackConfirmation = codecForRecoupConfirmation().decode(await resp.json());
if (paybackConfirmation.reserve_pub !== coin.reservePub) {
throw Error(`Coin's reserve doesn't match reserve on payback`);
}
diff --git a/src/operations/pending.ts b/src/operations/pending.ts
index 360180854..ed3b59d71 100644
--- a/src/operations/pending.ts
+++ b/src/operations/pending.ts
@@ -27,7 +27,7 @@ import {
PendingOperationsResponse,
PendingOperationType,
} from "../types/pending";
-import { Duration, getTimestampNow, Timestamp } from "../types/walletTypes";
+import { Duration, getTimestampNow, Timestamp, getDurationRemaining, durationMin } from "../util/time";
import { TransactionHandle } from "../util/query";
import { InternalWalletState } from "./state";
@@ -36,10 +36,8 @@ function updateRetryDelay(
now: Timestamp,
retryTimestamp: Timestamp,
): Duration {
- if (retryTimestamp.t_ms <= now.t_ms) {
- return { d_ms: 0 };
- }
- return { d_ms: Math.min(oldDelay.d_ms, retryTimestamp.t_ms - now.t_ms) };
+ const remaining = getDurationRemaining(retryTimestamp, now);
+ return durationMin(oldDelay, remaining);
}
async function gatherExchangePending(
@@ -278,7 +276,7 @@ async function gatherProposalPending(
resp.pendingOperations.push({
type: PendingOperationType.ProposalChoice,
givesLifeness: false,
- merchantBaseUrl: proposal.download!!.contractTerms.merchant_base_url,
+ merchantBaseUrl: proposal.download!!.contractData.merchantBaseUrl,
proposalId: proposal.proposalId,
proposalTimestamp: proposal.timestamp,
});
diff --git a/src/operations/refresh.ts b/src/operations/refresh.ts
index 8390cac54..87d81cb2d 100644
--- a/src/operations/refresh.ts
+++ b/src/operations/refresh.ts
@@ -34,7 +34,6 @@ import { Logger } from "../util/logging";
import { getWithdrawDenomList } from "./withdraw";
import { updateExchangeFromUrl } from "./exchanges";
import {
- getTimestampNow,
OperationError,
CoinPublicKey,
RefreshReason,
@@ -43,6 +42,7 @@ import {
import { guardOperationException } from "./errors";
import { NotificationType } from "../types/notifications";
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
+import { getTimestampNow } from "../util/time";
const logger = new Logger("refresh.ts");
diff --git a/src/operations/refund.ts b/src/operations/refund.ts
index b4139c991..6a96868a3 100644
--- a/src/operations/refund.ts
+++ b/src/operations/refund.ts
@@ -26,7 +26,6 @@
import { InternalWalletState } from "./state";
import {
OperationError,
- getTimestampNow,
RefreshReason,
CoinPublicKey,
} from "../types/walletTypes";
@@ -47,12 +46,14 @@ import {
MerchantRefundPermission,
MerchantRefundResponse,
RefundRequest,
+ codecForMerchantRefundResponse,
} from "../types/talerTypes";
import { AmountJson } from "../util/amounts";
import { guardOperationException, OperationFailedError } from "./errors";
import { randomBytes } from "../crypto/primitives/nacl-fast";
import { encodeCrock } from "../crypto/talerCrypto";
import { HttpResponseStatus } from "../util/http";
+import { getTimestampNow } from "../util/time";
async function incrementPurchaseQueryRefundRetry(
ws: InternalWalletState,
@@ -288,7 +289,7 @@ export async function applyRefund(
console.log("processing purchase for refund");
await startRefundQuery(ws, purchase.proposalId);
- return purchase.contractTermsHash;
+ return purchase.contractData.contractTermsHash;
}
export async function processPurchaseQueryRefund(
@@ -334,9 +335,9 @@ async function processPurchaseQueryRefundImpl(
const refundUrlObj = new URL(
"refund",
- purchase.contractTerms.merchant_base_url,
+ purchase.contractData.merchantBaseUrl,
);
- refundUrlObj.searchParams.set("order_id", purchase.contractTerms.order_id);
+ refundUrlObj.searchParams.set("order_id", purchase.contractData.orderId);
const refundUrl = refundUrlObj.href;
let resp;
try {
@@ -349,7 +350,7 @@ async function processPurchaseQueryRefundImpl(
throw Error(`unexpected status code (${resp.status}) for /refund`);
}
- const refundResponse = MerchantRefundResponse.checked(await resp.json());
+ const refundResponse = codecForMerchantRefundResponse().decode(await resp.json());
await acceptRefundResponse(
ws,
proposalId,
@@ -409,8 +410,8 @@ async function processPurchaseApplyRefundImpl(
const perm = info.perm;
const req: RefundRequest = {
coin_pub: perm.coin_pub,
- h_contract_terms: purchase.contractTermsHash,
- merchant_pub: purchase.contractTerms.merchant_pub,
+ h_contract_terms: purchase.contractData.contractTermsHash,
+ merchant_pub: purchase.contractData.merchantPub,
merchant_sig: perm.merchant_sig,
refund_amount: perm.refund_amount,
refund_fee: perm.refund_fee,
diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts
index 7be927824..2dedf17de 100644
--- a/src/operations/reserves.ts
+++ b/src/operations/reserves.ts
@@ -17,7 +17,6 @@
import {
CreateReserveRequest,
CreateReserveResponse,
- getTimestampNow,
ConfirmReserveRequest,
OperationError,
AcceptWithdrawalResponse,
@@ -42,7 +41,7 @@ import {
getExchangeTrust,
getExchangePaytoUri,
} from "./exchanges";
-import { WithdrawOperationStatusResponse } from "../types/talerTypes";
+import { WithdrawOperationStatusResponse, codecForWithdrawOperationStatusResponse } from "../types/talerTypes";
import { assertUnreachable } from "../util/assertUnreachable";
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto";
import { randomBytes } from "../crypto/primitives/nacl-fast";
@@ -57,6 +56,7 @@ import {
} from "./errors";
import { NotificationType } from "../types/notifications";
import { codecForReserveStatus } from "../types/ReserveStatus";
+import { getTimestampNow } from "../util/time";
const logger = new Logger("reserves.ts");
@@ -289,7 +289,7 @@ async function processReserveBankStatusImpl(
`unexpected status ${statusResp.status} for bank status query`,
);
}
- status = WithdrawOperationStatusResponse.checked(await statusResp.json());
+ status = codecForWithdrawOperationStatusResponse().decode(await statusResp.json());
} catch (e) {
throw e;
}
@@ -390,6 +390,7 @@ async function updateReserve(
let resp;
try {
resp = await ws.http.get(reqUrl.href);
+ console.log("got reserve/status response", await resp.json());
if (resp.status === 404) {
const m = "The exchange does not know about this reserve (yet).";
await incrementReserveRetry(ws, reservePub, undefined);
@@ -408,7 +409,7 @@ async function updateReserve(
throw new OperationFailedAndReportedError(m);
}
const respJson = await resp.json();
- const reserveInfo = codecForReserveStatus.decode(respJson);
+ const reserveInfo = codecForReserveStatus().decode(respJson);
const balance = Amounts.parseOrThrow(reserveInfo.balance);
await ws.db.runWithWriteTransaction(
[Stores.reserves, Stores.reserveUpdatedEvents],
diff --git a/src/operations/return.ts b/src/operations/return.ts
deleted file mode 100644
index 4238f6cd2..000000000
--- a/src/operations/return.ts
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- 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 {
- ReturnCoinsRequest,
- CoinWithDenom,
-} from "../types/walletTypes";
-import { Database } from "../util/query";
-import { InternalWalletState } from "./state";
-import { Stores, TipRecord, CoinStatus, CoinsReturnRecord, CoinRecord } from "../types/dbTypes";
-import * as Amounts from "../util/amounts";
-import { AmountJson } from "../util/amounts";
-import { Logger } from "../util/logging";
-import { canonicalJson } from "../util/helpers";
-import { ContractTerms } from "../types/talerTypes";
-import { selectPayCoins } from "./pay";
-
-const logger = new Logger("return.ts");
-
-async function getCoinsForReturn(
- ws: InternalWalletState,
- exchangeBaseUrl: string,
- amount: AmountJson,
-): Promise<CoinWithDenom[] | undefined> {
- const exchange = await ws.db.get(
- Stores.exchanges,
- exchangeBaseUrl,
- );
- if (!exchange) {
- throw Error(`Exchange ${exchangeBaseUrl} not known to the wallet`);
- }
-
- const coins: CoinRecord[] = await ws.db.iterIndex(
- Stores.coins.exchangeBaseUrlIndex,
- exchange.baseUrl,
- ).toArray();
-
- if (!coins || !coins.length) {
- return [];
- }
-
- const denoms = await ws.db.iterIndex(
- Stores.denominations.exchangeBaseUrlIndex,
- exchange.baseUrl,
- ).toArray();
-
- // Denomination of the first coin, we assume that all other
- // coins have the same currency
- const firstDenom = await ws.db.get(Stores.denominations, [
- exchange.baseUrl,
- coins[0].denomPub,
- ]);
- if (!firstDenom) {
- throw Error("db inconsistent");
- }
- const currency = firstDenom.value.currency;
-
- const cds: CoinWithDenom[] = [];
- for (const coin of coins) {
- const denom = await ws.db.get(Stores.denominations, [
- exchange.baseUrl,
- coin.denomPub,
- ]);
- if (!denom) {
- throw Error("db inconsistent");
- }
- if (denom.value.currency !== currency) {
- console.warn(
- `same pubkey for different currencies at exchange ${exchange.baseUrl}`,
- );
- continue;
- }
- if (coin.suspended) {
- continue;
- }
- if (coin.status !== CoinStatus.Fresh) {
- continue;
- }
- cds.push({ coin, denom });
- }
-
- const res = selectPayCoins(denoms, cds, amount, amount);
- if (res) {
- return res.cds;
- }
- return undefined;
-}
-
-
-/**
- * Trigger paying coins back into the user's account.
- */
-export async function returnCoins(
- ws: InternalWalletState,
- req: ReturnCoinsRequest,
-): Promise<void> {
- logger.trace("got returnCoins request", req);
- const wireType = (req.senderWire as any).type;
- logger.trace("wireType", wireType);
- if (!wireType || typeof wireType !== "string") {
- console.error(`wire type must be a non-empty string, not ${wireType}`);
- return;
- }
- const stampSecNow = Math.floor(new Date().getTime() / 1000);
- const exchange = await ws.db.get(Stores.exchanges, req.exchange);
- if (!exchange) {
- console.error(`Exchange ${req.exchange} not known to the wallet`);
- return;
- }
- const exchangeDetails = exchange.details;
- if (!exchangeDetails) {
- throw Error("exchange information needs to be updated first.");
- }
- logger.trace("selecting coins for return:", req);
- const cds = await getCoinsForReturn(ws, req.exchange, req.amount);
- logger.trace(cds);
-
- if (!cds) {
- throw Error("coin return impossible, can't select coins");
- }
-
- const { priv, pub } = await ws.cryptoApi.createEddsaKeypair();
-
- const wireHash = await ws.cryptoApi.hashString(
- canonicalJson(req.senderWire),
- );
-
- const contractTerms: ContractTerms = {
- H_wire: wireHash,
- amount: Amounts.toString(req.amount),
- auditors: [],
- exchanges: [
- { master_pub: exchangeDetails.masterPublicKey, url: exchange.baseUrl },
- ],
- extra: {},
- fulfillment_url: "",
- locations: [],
- max_fee: Amounts.toString(req.amount),
- merchant: {},
- merchant_pub: pub,
- order_id: "none",
- pay_deadline: `/Date(${stampSecNow + 30 * 5})/`,
- wire_transfer_deadline: `/Date(${stampSecNow + 60 * 5})/`,
- merchant_base_url: "taler://return-to-account",
- products: [],
- refund_deadline: `/Date(${stampSecNow + 60 * 5})/`,
- timestamp: `/Date(${stampSecNow})/`,
- wire_method: wireType,
- };
-
- const contractTermsHash = await ws.cryptoApi.hashString(
- canonicalJson(contractTerms),
- );
-
- const payCoinInfo = await ws.cryptoApi.signDeposit(
- contractTerms,
- cds,
- Amounts.parseOrThrow(contractTerms.amount),
- );
-
- logger.trace("pci", payCoinInfo);
-
- const coins = payCoinInfo.coinInfo.map(s => ({ coinPaySig: s.sig }));
-
- const coinsReturnRecord: CoinsReturnRecord = {
- coins,
- contractTerms,
- contractTermsHash,
- exchange: exchange.baseUrl,
- merchantPriv: priv,
- wire: req.senderWire,
- };
-
- await ws.db.runWithWriteTransaction(
- [Stores.coinsReturns, Stores.coins],
- async tx => {
- await tx.put(Stores.coinsReturns, coinsReturnRecord);
- for (let coinInfo of payCoinInfo.coinInfo) {
- const coin = await tx.get(Stores.coins, coinInfo.coinPub);
- if (!coin) {
- throw Error("coin allocated for deposit not in database anymore");
- }
- const remaining = Amounts.sub(coin.currentAmount, coinInfo.subtractedAmount);
- if (remaining.saturated) {
- throw Error("coin allocated for deposit does not have enough balance");
- }
- coin.currentAmount = remaining.amount;
- await tx.put(Stores.coins, coin);
- }
- },
- );
-
- depositReturnedCoins(ws, coinsReturnRecord);
-}
-
-async function depositReturnedCoins(
- ws: InternalWalletState,
- coinsReturnRecord: CoinsReturnRecord,
-): Promise<void> {
- for (const c of coinsReturnRecord.coins) {
- if (c.depositedSig) {
- continue;
- }
- const req = {
- H_wire: coinsReturnRecord.contractTerms.H_wire,
- coin_pub: c.coinPaySig.coin_pub,
- coin_sig: c.coinPaySig.coin_sig,
- contribution: c.coinPaySig.contribution,
- denom_pub: c.coinPaySig.denom_pub,
- h_contract_terms: coinsReturnRecord.contractTermsHash,
- merchant_pub: coinsReturnRecord.contractTerms.merchant_pub,
- pay_deadline: coinsReturnRecord.contractTerms.pay_deadline,
- refund_deadline: coinsReturnRecord.contractTerms.refund_deadline,
- timestamp: coinsReturnRecord.contractTerms.timestamp,
- ub_sig: c.coinPaySig.ub_sig,
- wire: coinsReturnRecord.wire,
- wire_transfer_deadline: coinsReturnRecord.contractTerms.pay_deadline,
- };
- logger.trace("req", req);
- const reqUrl = new URL("deposit", coinsReturnRecord.exchange);
- const resp = await ws.http.postJson(reqUrl.href, req);
- if (resp.status !== 200) {
- console.error("deposit failed due to status code", resp);
- continue;
- }
- const respJson = await resp.json();
- if (respJson.status !== "DEPOSIT_OK") {
- console.error("deposit failed", resp);
- continue;
- }
-
- if (!respJson.sig) {
- console.error("invalid 'sig' field", resp);
- continue;
- }
-
- // FIXME: verify signature
-
- // For every successful deposit, we replace the old record with an updated one
- const currentCrr = await ws.db.get(
- Stores.coinsReturns,
- coinsReturnRecord.contractTermsHash,
- );
- if (!currentCrr) {
- console.error("database inconsistent");
- continue;
- }
- for (const nc of currentCrr.coins) {
- if (nc.coinPaySig.coin_pub === c.coinPaySig.coin_pub) {
- nc.depositedSig = respJson.sig;
- }
- }
- await ws.db.put(Stores.coinsReturns, currentCrr);
- }
-}
diff --git a/src/operations/tip.ts b/src/operations/tip.ts
index 76d0df22d..fcdda0763 100644
--- a/src/operations/tip.ts
+++ b/src/operations/tip.ts
@@ -18,13 +18,14 @@ import { InternalWalletState } from "./state";
import { parseTipUri } from "../util/taleruri";
import {
TipStatus,
- getTimestampNow,
OperationError,
} from "../types/walletTypes";
import {
TipPickupGetResponse,
TipPlanchetDetail,
TipResponse,
+ codecForTipPickupGetResponse,
+ codecForTipResponse,
} from "../types/talerTypes";
import * as Amounts from "../util/amounts";
import {
@@ -39,11 +40,11 @@ import {
getVerifiedWithdrawDenomList,
processWithdrawSession,
} from "./withdraw";
-import { getTalerStampSec, extractTalerStampOrThrow } from "../util/helpers";
import { updateExchangeFromUrl } from "./exchanges";
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
import { guardOperationException } from "./errors";
import { NotificationType } from "../types/notifications";
+import { getTimestampNow } from "../util/time";
export async function getTipStatus(
ws: InternalWalletState,
@@ -63,7 +64,7 @@ export async function getTipStatus(
}
const respJson = await merchantResp.json();
console.log("resp:", respJson);
- const tipPickupStatus = TipPickupGetResponse.checked(respJson);
+ const tipPickupStatus = codecForTipPickupGetResponse().decode(respJson);
console.log("status", tipPickupStatus);
@@ -88,7 +89,7 @@ export async function getTipStatus(
acceptedTimestamp: undefined,
rejectedTimestamp: undefined,
amount,
- deadline: extractTalerStampOrThrow(tipPickupStatus.stamp_expire),
+ deadline: tipPickupStatus.stamp_expire,
exchangeUrl: tipPickupStatus.exchange_url,
merchantBaseUrl: res.merchantBaseUrl,
nextUrl: undefined,
@@ -115,8 +116,8 @@ export async function getTipStatus(
nextUrl: tipPickupStatus.extra.next_url,
merchantOrigin: res.merchantOrigin,
merchantTipId: res.merchantTipId,
- expirationTimestamp: getTalerStampSec(tipPickupStatus.stamp_expire)!,
- timestamp: getTalerStampSec(tipPickupStatus.stamp_created)!,
+ expirationTimestamp: tipPickupStatus.stamp_expire,
+ timestamp: tipPickupStatus.stamp_created,
totalFees: tipRecord.totalFees,
tipId: tipRecord.tipId,
};
@@ -240,7 +241,7 @@ async function processTipImpl(
throw e;
}
- const response = TipResponse.checked(await merchantResp.json());
+ const response = codecForTipResponse().decode(await merchantResp.json());
if (response.reserve_sigs.length !== tipRecord.planchets.length) {
throw Error("number of tip responses does not match requested planchets");
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index 38baffa8d..27156015d 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -27,33 +27,39 @@ import {
} from "../types/dbTypes";
import * as Amounts from "../util/amounts";
import {
- getTimestampNow,
- AcceptWithdrawalResponse,
BankWithdrawDetails,
ExchangeWithdrawDetails,
WithdrawDetails,
OperationError,
} from "../types/walletTypes";
-import { WithdrawOperationStatusResponse } from "../types/talerTypes";
+import { WithdrawOperationStatusResponse, codecForWithdrawOperationStatusResponse } from "../types/talerTypes";
import { InternalWalletState } from "./state";
import { parseWithdrawUri } from "../util/taleruri";
import { Logger } from "../util/logging";
-import {
- updateExchangeFromUrl,
- getExchangeTrust,
-} from "./exchanges";
+import { updateExchangeFromUrl, getExchangeTrust } from "./exchanges";
import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions";
import * as LibtoolVersion from "../util/libtoolVersion";
import { guardOperationException } from "./errors";
import { NotificationType } from "../types/notifications";
+import {
+ getTimestampNow,
+ getDurationRemaining,
+ timestampCmp,
+ timestampSubtractDuraction,
+} from "../util/time";
const logger = new Logger("withdraw.ts");
function isWithdrawableDenom(d: DenominationRecord) {
const now = getTimestampNow();
- const started = now.t_ms >= d.stampStart.t_ms;
- const stillOkay = d.stampExpireWithdraw.t_ms + 60 * 1000 > now.t_ms;
+ const started = timestampCmp(now, d.stampStart) >= 0;
+ const lastPossibleWithdraw = timestampSubtractDuraction(
+ d.stampExpireWithdraw,
+ { d_ms: 50 * 1000 },
+ );
+ const remaining = getDurationRemaining(lastPossibleWithdraw, now);
+ const stillOkay = remaining.d_ms !== 0;
return started && stillOkay;
}
@@ -108,11 +114,14 @@ export async function getBankWithdrawalInfo(
}
const resp = await ws.http.get(uriResult.statusUrl);
if (resp.status !== 200) {
- throw Error(`unexpected status (${resp.status}) from bank for ${uriResult.statusUrl}`);
+ throw Error(
+ `unexpected status (${resp.status}) from bank for ${uriResult.statusUrl}`,
+ );
}
const respJson = await resp.json();
console.log("resp:", respJson);
- const status = WithdrawOperationStatusResponse.checked(respJson);
+
+ const status = codecForWithdrawOperationStatusResponse().decode(respJson);
return {
amount: Amounts.parseOrThrow(status.amount),
confirmTransferUrl: status.confirm_transfer_url,
@@ -125,20 +134,18 @@ export async function getBankWithdrawalInfo(
};
}
-
async function getPossibleDenoms(
ws: InternalWalletState,
exchangeBaseUrl: string,
): Promise<DenominationRecord[]> {
- return await ws.db.iterIndex(
- Stores.denominations.exchangeBaseUrlIndex,
- exchangeBaseUrl,
- ).filter(d => {
- return (
- d.status === DenominationStatus.Unverified ||
- d.status === DenominationStatus.VerifiedGood
- );
- });
+ return await ws.db
+ .iterIndex(Stores.denominations.exchangeBaseUrlIndex, exchangeBaseUrl)
+ .filter(d => {
+ return (
+ d.status === DenominationStatus.Unverified ||
+ d.status === DenominationStatus.VerifiedGood
+ );
+ });
}
/**
@@ -204,8 +211,11 @@ async function processPlanchet(
planchet.denomPub,
);
-
- const isValid = await ws.cryptoApi.rsaVerify(planchet.coinPub, denomSig, planchet.denomPub);
+ const isValid = await ws.cryptoApi.rsaVerify(
+ planchet.coinPub,
+ denomSig,
+ planchet.denomPub,
+ );
if (!isValid) {
throw Error("invalid RSA signature by the exchange");
}
@@ -261,7 +271,10 @@ async function processPlanchet(
r.amountWithdrawCompleted,
Amounts.add(denom.value, denom.feeWithdraw).amount,
).amount;
- if (Amounts.cmp(r.amountWithdrawCompleted, r.amountWithdrawAllocated) == 0) {
+ if (
+ Amounts.cmp(r.amountWithdrawCompleted, r.amountWithdrawAllocated) ==
+ 0
+ ) {
reserveDepleted = true;
}
await tx.put(Stores.reserves, r);
@@ -273,9 +286,9 @@ async function processPlanchet(
);
if (success) {
- ws.notify( {
+ ws.notify({
type: NotificationType.CoinWithdrawn,
- } );
+ });
}
if (withdrawSessionFinished) {
@@ -436,10 +449,10 @@ async function processWithdrawCoin(
return;
}
- const coin = await ws.db.getIndexed(
- Stores.coins.byWithdrawalWithIdx,
- [withdrawalSessionId, coinIndex],
- );
+ const coin = await ws.db.getIndexed(Stores.coins.byWithdrawalWithIdx, [
+ withdrawalSessionId,
+ coinIndex,
+ ]);
if (coin) {
console.log("coin already exists");
@@ -494,7 +507,7 @@ async function resetWithdrawSessionRetry(
ws: InternalWalletState,
withdrawalSessionId: string,
) {
- await ws.db.mutate(Stores.withdrawalSession, withdrawalSessionId, (x) => {
+ await ws.db.mutate(Stores.withdrawalSession, withdrawalSessionId, x => {
if (x.retryInfo.active) {
x.retryInfo = initRetryInfo();
}
@@ -570,16 +583,12 @@ export async function getExchangeWithdrawalInfo(
}
}
- const possibleDenoms = await ws.db.iterIndex(
- Stores.denominations.exchangeBaseUrlIndex,
- baseUrl,
- ).filter(d => d.isOffered);
+ const possibleDenoms = await ws.db
+ .iterIndex(Stores.denominations.exchangeBaseUrlIndex, baseUrl)
+ .filter(d => d.isOffered);
const trustedAuditorPubs = [];
- const currencyRecord = await ws.db.get(
- Stores.currencies,
- amount.currency,
- );
+ const currencyRecord = await ws.db.get(Stores.currencies, amount.currency);
if (currencyRecord) {
trustedAuditorPubs.push(...currencyRecord.auditors.map(a => a.auditorPub));
}
@@ -606,7 +615,10 @@ export async function getExchangeWithdrawalInfo(
let tosAccepted = false;
if (exchangeInfo.termsOfServiceAcceptedTimestamp) {
- if (exchangeInfo.termsOfServiceAcceptedEtag == exchangeInfo.termsOfServiceLastEtag) {
+ if (
+ exchangeInfo.termsOfServiceAcceptedEtag ==
+ exchangeInfo.termsOfServiceLastEtag
+ ) {
tosAccepted = true;
}
}