all retryInfo function in the same namespace, adding missing retryInfo increment
This commit is contained in:
parent
d3a857743d
commit
c67d0bff1d
@ -120,7 +120,10 @@ export namespace BankApi {
|
|||||||
if (respJson.paytoUri) {
|
if (respJson.paytoUri) {
|
||||||
paytoUri = respJson.paytoUri;
|
paytoUri = respJson.paytoUri;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
logger.error("error trying to parse json from response", e);
|
||||||
|
throw TalerError.fromException(e);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
password,
|
password,
|
||||||
username,
|
username,
|
||||||
|
@ -15,54 +15,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BackupPurchase,
|
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts, BackupCoinSourceType, BackupDenomSel, BackupProposalStatus,
|
||||||
BackupDenomSel,
|
BackupPurchase, BackupRefreshReason, BackupRefundState, codecForContractTerms,
|
||||||
WalletBackupContentV1,
|
DenomKeyType, j2s, Logger, RefreshReason, TalerProtocolTimestamp,
|
||||||
BackupCoinSourceType,
|
WalletBackupContentV1
|
||||||
BackupProposalStatus,
|
|
||||||
codecForContractTerms,
|
|
||||||
BackupRefundState,
|
|
||||||
RefreshReason,
|
|
||||||
BackupRefreshReason,
|
|
||||||
DenomKeyType,
|
|
||||||
AbsoluteTime,
|
|
||||||
TalerProtocolTimestamp,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
WalletContractData,
|
AbortStatus, CoinSource,
|
||||||
DenomSelectionState,
|
|
||||||
DenominationVerificationStatus,
|
|
||||||
CoinSource,
|
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
CoinStatus,
|
CoinStatus, DenominationVerificationStatus, DenomSelectionState, OperationStatus, ProposalDownload,
|
||||||
ReserveBankInfo,
|
ProposalStatus, RefreshCoinStatus, RefreshSessionRecord, RefundState, ReserveBankInfo,
|
||||||
ReserveRecordStatus,
|
ReserveRecordStatus, WalletContractData, WalletRefundItem, WalletStoresV1, WireInfo
|
||||||
ProposalDownload,
|
|
||||||
ProposalStatus,
|
|
||||||
WalletRefundItem,
|
|
||||||
RefundState,
|
|
||||||
AbortStatus,
|
|
||||||
RefreshSessionRecord,
|
|
||||||
WireInfo,
|
|
||||||
WalletStoresV1,
|
|
||||||
RefreshCoinStatus,
|
|
||||||
OperationStatus,
|
|
||||||
} from "../../db.js";
|
} from "../../db.js";
|
||||||
|
import { InternalWalletState } from "../../internal-wallet-state.js";
|
||||||
import { PayCoinSelection } from "../../util/coinSelection.js";
|
import { PayCoinSelection } from "../../util/coinSelection.js";
|
||||||
import { j2s } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
import {
|
||||||
checkDbInvariant,
|
checkDbInvariant,
|
||||||
checkLogicInvariant,
|
checkLogicInvariant
|
||||||
} from "../../util/invariants.js";
|
} from "../../util/invariants.js";
|
||||||
import { Logger } from "@gnu-taler/taler-util";
|
|
||||||
import { resetRetryInfo } from "../../util/retries.js";
|
|
||||||
import { InternalWalletState } from "../../internal-wallet-state.js";
|
|
||||||
import { provideBackupState } from "./state.js";
|
|
||||||
import { makeEventId, TombstoneTag } from "../transactions.js";
|
|
||||||
import { getExchangeDetails } from "../exchanges.js";
|
|
||||||
import { GetReadOnlyAccess, GetReadWriteAccess } from "../../util/query.js";
|
import { GetReadOnlyAccess, GetReadWriteAccess } from "../../util/query.js";
|
||||||
|
import { RetryInfo } from "../../util/retries.js";
|
||||||
|
import { getExchangeDetails } from "../exchanges.js";
|
||||||
|
import { makeEventId, TombstoneTag } from "../transactions.js";
|
||||||
|
import { provideBackupState } from "./state.js";
|
||||||
|
|
||||||
const logger = new Logger("operations/backup/import.ts");
|
const logger = new Logger("operations/backup/import.ts");
|
||||||
|
|
||||||
@ -276,7 +252,7 @@ export async function importBackup(
|
|||||||
protocolVersionRange: backupExchange.protocol_version_range,
|
protocolVersionRange: backupExchange.protocol_version_range,
|
||||||
},
|
},
|
||||||
permanent: true,
|
permanent: true,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastUpdate: undefined,
|
lastUpdate: undefined,
|
||||||
nextUpdate: TalerProtocolTimestamp.now(),
|
nextUpdate: TalerProtocolTimestamp.now(),
|
||||||
nextRefreshCheck: TalerProtocolTimestamp.now(),
|
nextRefreshCheck: TalerProtocolTimestamp.now(),
|
||||||
@ -464,7 +440,7 @@ export async function importBackup(
|
|||||||
timestampReserveInfoPosted:
|
timestampReserveInfoPosted:
|
||||||
backupReserve.bank_info?.timestamp_reserve_info_posted,
|
backupReserve.bank_info?.timestamp_reserve_info_posted,
|
||||||
senderWire: backupReserve.sender_wire,
|
senderWire: backupReserve.sender_wire,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
initialWithdrawalGroupId:
|
initialWithdrawalGroupId:
|
||||||
backupReserve.initial_withdrawal_group_id,
|
backupReserve.initial_withdrawal_group_id,
|
||||||
@ -505,7 +481,7 @@ export async function importBackup(
|
|||||||
backupWg.raw_withdrawal_amount,
|
backupWg.raw_withdrawal_amount,
|
||||||
),
|
),
|
||||||
reservePub,
|
reservePub,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
secretSeed: backupWg.secret_seed,
|
secretSeed: backupWg.secret_seed,
|
||||||
timestampStart: backupWg.timestamp_created,
|
timestampStart: backupWg.timestamp_created,
|
||||||
timestampFinish: backupWg.timestamp_finish,
|
timestampFinish: backupWg.timestamp_finish,
|
||||||
@ -618,7 +594,7 @@ export async function importBackup(
|
|||||||
cryptoComp.proposalNoncePrivToPub[backupProposal.nonce_priv],
|
cryptoComp.proposalNoncePrivToPub[backupProposal.nonce_priv],
|
||||||
proposalId: backupProposal.proposal_id,
|
proposalId: backupProposal.proposal_id,
|
||||||
repurchaseProposalId: backupProposal.repurchase_proposal_id,
|
repurchaseProposalId: backupProposal.repurchase_proposal_id,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
download,
|
download,
|
||||||
proposalStatus,
|
proposalStatus,
|
||||||
});
|
});
|
||||||
@ -753,7 +729,7 @@ export async function importBackup(
|
|||||||
cryptoComp.proposalNoncePrivToPub[backupPurchase.nonce_priv],
|
cryptoComp.proposalNoncePrivToPub[backupPurchase.nonce_priv],
|
||||||
lastPayError: undefined,
|
lastPayError: undefined,
|
||||||
autoRefundDeadline: TalerProtocolTimestamp.never(),
|
autoRefundDeadline: TalerProtocolTimestamp.never(),
|
||||||
refundStatusRetryInfo: resetRetryInfo(),
|
refundStatusRetryInfo: RetryInfo.reset(),
|
||||||
lastRefundStatusError: undefined,
|
lastRefundStatusError: undefined,
|
||||||
refundAwaiting: undefined,
|
refundAwaiting: undefined,
|
||||||
timestampAccept: backupPurchase.timestamp_accept,
|
timestampAccept: backupPurchase.timestamp_accept,
|
||||||
@ -764,7 +740,7 @@ export async function importBackup(
|
|||||||
lastSessionId: undefined,
|
lastSessionId: undefined,
|
||||||
abortStatus,
|
abortStatus,
|
||||||
// FIXME!
|
// FIXME!
|
||||||
payRetryInfo: resetRetryInfo(),
|
payRetryInfo: RetryInfo.reset(),
|
||||||
download,
|
download,
|
||||||
paymentSubmitPending:
|
paymentSubmitPending:
|
||||||
!backupPurchase.timestamp_first_successful_pay,
|
!backupPurchase.timestamp_first_successful_pay,
|
||||||
@ -865,7 +841,7 @@ export async function importBackup(
|
|||||||
Amounts.parseOrThrow(x.estimated_output_amount),
|
Amounts.parseOrThrow(x.estimated_output_amount),
|
||||||
),
|
),
|
||||||
refreshSessionPerCoin,
|
refreshSessionPerCoin,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -891,7 +867,7 @@ export async function importBackup(
|
|||||||
merchantBaseUrl: backupTip.exchange_base_url,
|
merchantBaseUrl: backupTip.exchange_base_url,
|
||||||
merchantTipId: backupTip.merchant_tip_id,
|
merchantTipId: backupTip.merchant_tip_id,
|
||||||
pickedUpTimestamp: backupTip.timestamp_finished,
|
pickedUpTimestamp: backupTip.timestamp_finished,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
secretSeed: backupTip.secret_seed,
|
secretSeed: backupTip.secret_seed,
|
||||||
tipAmountEffective: denomsSel.totalCoinValue,
|
tipAmountEffective: denomsSel.totalCoinValue,
|
||||||
tipAmountRaw: Amounts.parseOrThrow(backupTip.tip_amount_raw),
|
tipAmountRaw: Amounts.parseOrThrow(backupTip.tip_amount_raw),
|
||||||
|
@ -25,10 +25,9 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
AmountString,
|
AbsoluteTime, AmountString,
|
||||||
BackupRecovery,
|
BackupRecovery,
|
||||||
buildCodecForObject,
|
buildCodecForObject, bytesToString, canonicalizeBaseUrl,
|
||||||
canonicalizeBaseUrl,
|
|
||||||
canonicalJson,
|
canonicalJson,
|
||||||
Codec,
|
Codec,
|
||||||
codecForAmountString,
|
codecForAmountString,
|
||||||
@ -37,39 +36,22 @@ import {
|
|||||||
codecForNumber,
|
codecForNumber,
|
||||||
codecForString,
|
codecForString,
|
||||||
codecOptional,
|
codecOptional,
|
||||||
ConfirmPayResultType,
|
ConfirmPayResultType, decodeCrock, DenomKeyType,
|
||||||
DenomKeyType,
|
durationFromSpec, eddsaGetPublic,
|
||||||
durationFromSpec,
|
|
||||||
hashDenomPub,
|
|
||||||
HttpStatusCode,
|
|
||||||
j2s,
|
|
||||||
Logger,
|
|
||||||
notEmpty,
|
|
||||||
PreparePayResultType,
|
|
||||||
RecoveryLoadRequest,
|
|
||||||
RecoveryMergeStrategy,
|
|
||||||
TalerErrorDetail,
|
|
||||||
AbsoluteTime,
|
|
||||||
URL,
|
|
||||||
WalletBackupContentV1,
|
|
||||||
TalerProtocolTimestamp,
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { gunzipSync, gzipSync } from "fflate";
|
|
||||||
import { InternalWalletState } from "../../internal-wallet-state.js";
|
|
||||||
import { kdf } from "@gnu-taler/taler-util";
|
|
||||||
import { secretbox, secretbox_open } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
|
||||||
bytesToString,
|
|
||||||
decodeCrock,
|
|
||||||
eddsaGetPublic,
|
|
||||||
EddsaKeyPair,
|
EddsaKeyPair,
|
||||||
encodeCrock,
|
encodeCrock,
|
||||||
getRandomBytes,
|
getRandomBytes,
|
||||||
hash,
|
hash, hashDenomPub,
|
||||||
rsaBlind,
|
HttpStatusCode,
|
||||||
stringToBytes,
|
j2s, kdf, Logger,
|
||||||
|
notEmpty,
|
||||||
|
PreparePayResultType,
|
||||||
|
RecoveryLoadRequest,
|
||||||
|
RecoveryMergeStrategy, rsaBlind, secretbox, secretbox_open, stringToBytes, TalerErrorDetail, TalerProtocolTimestamp, URL,
|
||||||
|
WalletBackupContentV1
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { CryptoDispatcher } from "../../crypto/workers/cryptoDispatcher.js";
|
import { gunzipSync, gzipSync } from "fflate";
|
||||||
|
import { TalerCryptoInterface } from "../../crypto/cryptoImplementation.js";
|
||||||
import {
|
import {
|
||||||
BackupProviderRecord,
|
BackupProviderRecord,
|
||||||
BackupProviderState,
|
BackupProviderState,
|
||||||
@ -78,28 +60,28 @@ import {
|
|||||||
ConfigRecord,
|
ConfigRecord,
|
||||||
WalletBackupConfState,
|
WalletBackupConfState,
|
||||||
WalletStoresV1,
|
WalletStoresV1,
|
||||||
WALLET_BACKUP_STATE_KEY,
|
WALLET_BACKUP_STATE_KEY
|
||||||
} from "../../db.js";
|
} from "../../db.js";
|
||||||
|
import { InternalWalletState } from "../../internal-wallet-state.js";
|
||||||
import {
|
import {
|
||||||
readSuccessResponseJsonOrThrow,
|
readSuccessResponseJsonOrThrow,
|
||||||
readTalerErrorResponse,
|
readTalerErrorResponse
|
||||||
} from "../../util/http.js";
|
} from "../../util/http.js";
|
||||||
import {
|
import {
|
||||||
checkDbInvariant,
|
checkDbInvariant,
|
||||||
checkLogicInvariant,
|
checkLogicInvariant
|
||||||
} from "../../util/invariants.js";
|
} from "../../util/invariants.js";
|
||||||
import { GetReadWriteAccess } from "../../util/query.js";
|
import { GetReadWriteAccess } from "../../util/query.js";
|
||||||
import { resetRetryInfo, updateRetryInfoTimeout } from "../../util/retries.js";
|
import { RetryInfo } from "../../util/retries.js";
|
||||||
|
import { guardOperationException } from "../common.js";
|
||||||
import {
|
import {
|
||||||
checkPaymentByProposalId,
|
checkPaymentByProposalId,
|
||||||
confirmPay,
|
confirmPay,
|
||||||
preparePayForUri,
|
preparePayForUri
|
||||||
} from "../pay.js";
|
} from "../pay.js";
|
||||||
import { exportBackup } from "./export.js";
|
import { exportBackup } from "./export.js";
|
||||||
import { BackupCryptoPrecomputedData, importBackup } from "./import.js";
|
import { BackupCryptoPrecomputedData, importBackup } from "./import.js";
|
||||||
import { getWalletBackupState, provideBackupState } from "./state.js";
|
import { getWalletBackupState, provideBackupState } from "./state.js";
|
||||||
import { guardOperationException } from "../common.js";
|
|
||||||
import { TalerCryptoInterface } from "../../crypto/cryptoImplementation.js";
|
|
||||||
|
|
||||||
const logger = new Logger("operations/backup.ts");
|
const logger = new Logger("operations/backup.ts");
|
||||||
|
|
||||||
@ -344,7 +326,7 @@ async function runBackupCycleForProvider(
|
|||||||
}
|
}
|
||||||
const res = await preparePayForUri(ws, talerUri);
|
const res = await preparePayForUri(ws, talerUri);
|
||||||
let proposalId = res.proposalId;
|
let proposalId = res.proposalId;
|
||||||
let doPay: boolean = false;
|
let doPay = false;
|
||||||
switch (res.status) {
|
switch (res.status) {
|
||||||
case PreparePayResultType.InsufficientBalance:
|
case PreparePayResultType.InsufficientBalance:
|
||||||
// FIXME: record in provider state!
|
// FIXME: record in provider state!
|
||||||
@ -434,7 +416,7 @@ async function runBackupCycleForProvider(
|
|||||||
// FIXME: Allocate error code for this situation?
|
// FIXME: Allocate error code for this situation?
|
||||||
prov.state = {
|
prov.state = {
|
||||||
tag: BackupProviderStateTag.Retrying,
|
tag: BackupProviderStateTag.Retrying,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
};
|
};
|
||||||
await tx.backupProvider.put(prov);
|
await tx.backupProvider.put(prov);
|
||||||
});
|
});
|
||||||
@ -472,13 +454,12 @@ async function incrementBackupRetryInTx(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pr.state.tag === BackupProviderStateTag.Retrying) {
|
if (pr.state.tag === BackupProviderStateTag.Retrying) {
|
||||||
pr.state.retryInfo.retryCounter++;
|
|
||||||
pr.state.lastError = err;
|
pr.state.lastError = err;
|
||||||
updateRetryInfoTimeout(pr.state.retryInfo);
|
pr.state.retryInfo = RetryInfo.increment(pr.state.retryInfo);
|
||||||
} else if (pr.state.tag === BackupProviderStateTag.Ready) {
|
} else if (pr.state.tag === BackupProviderStateTag.Ready) {
|
||||||
pr.state = {
|
pr.state = {
|
||||||
tag: BackupProviderStateTag.Retrying,
|
tag: BackupProviderStateTag.Retrying,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: err,
|
lastError: err,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -685,7 +666,9 @@ export async function addBackupProvider(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restoreFromRecoverySecret(): Promise<void> {}
|
export async function restoreFromRecoverySecret(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about one provider.
|
* Information about one provider.
|
||||||
|
@ -47,7 +47,7 @@ import { DepositGroupRecord, OperationStatus, WireFee } from "../db.js";
|
|||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { PayCoinSelection, selectPayCoins } from "../util/coinSelection.js";
|
import { PayCoinSelection, selectPayCoins } from "../util/coinSelection.js";
|
||||||
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
||||||
import { resetRetryInfo, RetryInfo } from "../util/retries.js";
|
import { RetryInfo } from "../util/retries.js";
|
||||||
import { guardOperationException } from "./common.js";
|
import { guardOperationException } from "./common.js";
|
||||||
import { getExchangeDetails } from "./exchanges.js";
|
import { getExchangeDetails } from "./exchanges.js";
|
||||||
import {
|
import {
|
||||||
@ -85,7 +85,7 @@ async function setupDepositGroupRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.resetRetry) {
|
if (options.resetRetry) {
|
||||||
x.retryInfo = resetRetryInfo();
|
x.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
x.retryInfo = RetryInfo.increment(x.retryInfo);
|
x.retryInfo = RetryInfo.increment(x.retryInfo);
|
||||||
}
|
}
|
||||||
@ -599,7 +599,7 @@ export async function createDepositGroup(
|
|||||||
payto_uri: req.depositPaytoUri,
|
payto_uri: req.depositPaytoUri,
|
||||||
salt: wireSalt,
|
salt: wireSalt,
|
||||||
},
|
},
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
operationStatus: OperationStatus.Pending,
|
operationStatus: OperationStatus.Pending,
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,7 @@ import {
|
|||||||
readSuccessResponseTextOrThrow,
|
readSuccessResponseTextOrThrow,
|
||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
|
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
|
||||||
import { resetRetryInfo, RetryInfo } from "../util/retries.js";
|
import { RetryInfo } from "../util/retries.js";
|
||||||
import {
|
import {
|
||||||
WALLET_CACHE_BREAKER_CLIENT_VERSION,
|
WALLET_CACHE_BREAKER_CLIENT_VERSION,
|
||||||
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
@ -116,6 +116,9 @@ async function reportExchangeUpdateError(
|
|||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!exchange.retryInfo) {
|
||||||
|
logger.reportBreak();
|
||||||
|
}
|
||||||
exchange.lastError = err;
|
exchange.lastError = err;
|
||||||
await tx.exchanges.put(exchange);
|
await tx.exchanges.put(exchange);
|
||||||
});
|
});
|
||||||
@ -137,7 +140,7 @@ async function setupExchangeUpdateRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
exchange.retryInfo = resetRetryInfo();
|
exchange.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
exchange.retryInfo = RetryInfo.increment(exchange.retryInfo);
|
exchange.retryInfo = RetryInfo.increment(exchange.retryInfo);
|
||||||
}
|
}
|
||||||
@ -399,7 +402,7 @@ async function provideExchangeRecord(
|
|||||||
const r: ExchangeRecord = {
|
const r: ExchangeRecord = {
|
||||||
permanent: true,
|
permanent: true,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
detailsPointer: undefined,
|
detailsPointer: undefined,
|
||||||
lastUpdate: undefined,
|
lastUpdate: undefined,
|
||||||
nextUpdate: AbsoluteTime.toTimestamp(now),
|
nextUpdate: AbsoluteTime.toTimestamp(now),
|
||||||
|
@ -97,10 +97,7 @@ import {
|
|||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { GetReadWriteAccess } from "../util/query.js";
|
import { GetReadWriteAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
getRetryDuration,
|
|
||||||
resetRetryInfo,
|
|
||||||
RetryInfo,
|
RetryInfo,
|
||||||
updateRetryInfoTimeout,
|
|
||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
import { getExchangeDetails } from "./exchanges.js";
|
import { getExchangeDetails } from "./exchanges.js";
|
||||||
import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
|
import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
|
||||||
@ -438,8 +435,8 @@ async function recordConfirmPay(
|
|||||||
proposalId: proposal.proposalId,
|
proposalId: proposal.proposalId,
|
||||||
lastPayError: undefined,
|
lastPayError: undefined,
|
||||||
lastRefundStatusError: undefined,
|
lastRefundStatusError: undefined,
|
||||||
payRetryInfo: resetRetryInfo(),
|
payRetryInfo: RetryInfo.reset(),
|
||||||
refundStatusRetryInfo: resetRetryInfo(),
|
refundStatusRetryInfo: RetryInfo.reset(),
|
||||||
refundQueryRequested: false,
|
refundQueryRequested: false,
|
||||||
timestampFirstSuccessfulPay: undefined,
|
timestampFirstSuccessfulPay: undefined,
|
||||||
autoRefundDeadline: undefined,
|
autoRefundDeadline: undefined,
|
||||||
@ -494,6 +491,7 @@ async function reportProposalError(
|
|||||||
logger.error(
|
logger.error(
|
||||||
`Asked to report an error for a proposal (${proposalId}) that is not active (no retryInfo)`,
|
`Asked to report an error for a proposal (${proposalId}) that is not active (no retryInfo)`,
|
||||||
);
|
);
|
||||||
|
logger.reportBreak();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pr.lastError = err;
|
pr.lastError = err;
|
||||||
@ -517,7 +515,7 @@ async function setupProposalRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
pr.retryInfo = resetRetryInfo();
|
pr.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
pr.retryInfo = RetryInfo.increment(pr.retryInfo);
|
pr.retryInfo = RetryInfo.increment(pr.retryInfo);
|
||||||
}
|
}
|
||||||
@ -541,7 +539,7 @@ async function setupPurchasePayRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
p.payRetryInfo = resetRetryInfo();
|
p.payRetryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
p.payRetryInfo = RetryInfo.increment(p.payRetryInfo);
|
p.payRetryInfo = RetryInfo.increment(p.payRetryInfo);
|
||||||
}
|
}
|
||||||
@ -610,7 +608,7 @@ async function failProposalPermanently(
|
|||||||
function getProposalRequestTimeout(proposal: ProposalRecord): Duration {
|
function getProposalRequestTimeout(proposal: ProposalRecord): Duration {
|
||||||
return durationMax(
|
return durationMax(
|
||||||
{ d_ms: 60000 },
|
{ d_ms: 60000 },
|
||||||
durationMin({ d_ms: 5000 }, getRetryDuration(proposal.retryInfo)),
|
durationMin({ d_ms: 5000 }, RetryInfo.getDuration(proposal.retryInfo)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,7 +936,7 @@ async function startDownloadProposal(
|
|||||||
proposalId: proposalId,
|
proposalId: proposalId,
|
||||||
proposalStatus: ProposalStatus.Downloading,
|
proposalStatus: ProposalStatus.Downloading,
|
||||||
repurchaseProposalId: undefined,
|
repurchaseProposalId: undefined,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
downloadSessionId: sessionId,
|
downloadSessionId: sessionId,
|
||||||
};
|
};
|
||||||
@ -986,14 +984,14 @@ async function storeFirstPaySuccess(
|
|||||||
purchase.paymentSubmitPending = false;
|
purchase.paymentSubmitPending = false;
|
||||||
purchase.lastPayError = undefined;
|
purchase.lastPayError = undefined;
|
||||||
purchase.lastSessionId = sessionId;
|
purchase.lastSessionId = sessionId;
|
||||||
purchase.payRetryInfo = resetRetryInfo();
|
purchase.payRetryInfo = RetryInfo.reset();
|
||||||
purchase.merchantPaySig = paySig;
|
purchase.merchantPaySig = paySig;
|
||||||
const protoAr = purchase.download.contractData.autoRefund;
|
const protoAr = purchase.download.contractData.autoRefund;
|
||||||
if (protoAr) {
|
if (protoAr) {
|
||||||
const ar = Duration.fromTalerProtocolDuration(protoAr);
|
const ar = Duration.fromTalerProtocolDuration(protoAr);
|
||||||
logger.info("auto_refund present");
|
logger.info("auto_refund present");
|
||||||
purchase.refundQueryRequested = true;
|
purchase.refundQueryRequested = true;
|
||||||
purchase.refundStatusRetryInfo = resetRetryInfo();
|
purchase.refundStatusRetryInfo = RetryInfo.reset();
|
||||||
purchase.lastRefundStatusError = undefined;
|
purchase.lastRefundStatusError = undefined;
|
||||||
purchase.autoRefundDeadline = AbsoluteTime.toTimestamp(
|
purchase.autoRefundDeadline = AbsoluteTime.toTimestamp(
|
||||||
AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
|
AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
|
||||||
@ -1023,7 +1021,7 @@ async function storePayReplaySuccess(
|
|||||||
}
|
}
|
||||||
purchase.paymentSubmitPending = false;
|
purchase.paymentSubmitPending = false;
|
||||||
purchase.lastPayError = undefined;
|
purchase.lastPayError = undefined;
|
||||||
purchase.payRetryInfo = resetRetryInfo();
|
purchase.payRetryInfo = RetryInfo.reset();
|
||||||
purchase.lastSessionId = sessionId;
|
purchase.lastSessionId = sessionId;
|
||||||
await tx.purchases.put(purchase);
|
await tx.purchases.put(purchase);
|
||||||
});
|
});
|
||||||
|
@ -26,38 +26,28 @@
|
|||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
Amounts,
|
Amounts,
|
||||||
codecForRecoupConfirmation,
|
codecForRecoupConfirmation, encodeCrock, getRandomBytes, j2s, Logger, NotificationType,
|
||||||
j2s,
|
|
||||||
NotificationType,
|
|
||||||
RefreshReason,
|
RefreshReason,
|
||||||
TalerErrorDetail,
|
TalerErrorDetail,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp, URL
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
import {
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
CoinStatus,
|
CoinStatus, OperationStatus, RecoupGroupRecord,
|
||||||
RecoupGroupRecord,
|
|
||||||
RefreshCoinSource,
|
RefreshCoinSource,
|
||||||
ReserveRecordStatus,
|
ReserveRecordStatus, WalletStoresV1, WithdrawCoinSource
|
||||||
WithdrawCoinSource,
|
|
||||||
WalletStoresV1,
|
|
||||||
OperationStatus,
|
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
||||||
import { Logger, URL } from "@gnu-taler/taler-util";
|
import { GetReadWriteAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
resetRetryInfo,
|
RetryInfo
|
||||||
RetryInfo,
|
|
||||||
updateRetryInfoTimeout,
|
|
||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
|
import { guardOperationException } from "./common.js";
|
||||||
import { createRefreshGroup, processRefreshGroup } from "./refresh.js";
|
import { createRefreshGroup, processRefreshGroup } from "./refresh.js";
|
||||||
import { getReserveRequestTimeout, processReserve } from "./reserves.js";
|
import { getReserveRequestTimeout, processReserve } from "./reserves.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
|
||||||
import { GetReadWriteAccess } from "../util/query.js";
|
|
||||||
import { guardOperationException } from "./common.js";
|
|
||||||
|
|
||||||
const logger = new Logger("operations/recoup.ts");
|
const logger = new Logger("operations/recoup.ts");
|
||||||
|
|
||||||
@ -78,7 +68,7 @@ async function setupRecoupRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
||||||
}
|
}
|
||||||
@ -139,7 +129,7 @@ async function putGroupAsFinished(
|
|||||||
if (allFinished) {
|
if (allFinished) {
|
||||||
logger.info("all recoups of recoup group are finished");
|
logger.info("all recoups of recoup group are finished");
|
||||||
recoupGroup.timestampFinished = TalerProtocolTimestamp.now();
|
recoupGroup.timestampFinished = TalerProtocolTimestamp.now();
|
||||||
recoupGroup.retryInfo = resetRetryInfo();
|
recoupGroup.retryInfo = RetryInfo.reset();
|
||||||
recoupGroup.lastError = undefined;
|
recoupGroup.lastError = undefined;
|
||||||
if (recoupGroup.scheduleRefreshCoins.length > 0) {
|
if (recoupGroup.scheduleRefreshCoins.length > 0) {
|
||||||
const refreshGroupId = await createRefreshGroup(
|
const refreshGroupId = await createRefreshGroup(
|
||||||
@ -278,7 +268,7 @@ async function recoupWithdrawCoin(
|
|||||||
const currency = updatedCoin.currentAmount.currency;
|
const currency = updatedCoin.currentAmount.currency;
|
||||||
updatedCoin.currentAmount = Amounts.getZero(currency);
|
updatedCoin.currentAmount = Amounts.getZero(currency);
|
||||||
updatedReserve.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
updatedReserve.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
||||||
updatedReserve.retryInfo = resetRetryInfo();
|
updatedReserve.retryInfo = RetryInfo.reset();
|
||||||
updatedReserve.operationStatus = OperationStatus.Pending;
|
updatedReserve.operationStatus = OperationStatus.Pending;
|
||||||
await tx.coins.put(updatedCoin);
|
await tx.coins.put(updatedCoin);
|
||||||
await tx.reserves.put(updatedReserve);
|
await tx.reserves.put(updatedReserve);
|
||||||
@ -482,7 +472,7 @@ export async function createRecoupGroup(
|
|||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
timestampFinished: undefined,
|
timestampFinished: undefined,
|
||||||
timestampStarted: TalerProtocolTimestamp.now(),
|
timestampStarted: TalerProtocolTimestamp.now(),
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
recoupFinishedPerCoin: coinPubs.map(() => false),
|
recoupFinishedPerCoin: coinPubs.map(() => false),
|
||||||
// Will be populated later
|
// Will be populated later
|
||||||
oldAmountPerCoin: [],
|
oldAmountPerCoin: [],
|
||||||
|
@ -15,20 +15,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AgeCommitment,
|
AbsoluteTime, AgeCommitment,
|
||||||
AgeRestriction,
|
AgeRestriction, AmountJson, Amounts, amountToPretty, codecForExchangeMeltResponse,
|
||||||
CoinPublicKeyString,
|
codecForExchangeRevealResponse,
|
||||||
DenomKeyType,
|
CoinPublicKey, CoinPublicKeyString,
|
||||||
encodeCrock,
|
DenomKeyType, Duration,
|
||||||
|
durationFromSpec,
|
||||||
|
durationMul, encodeCrock,
|
||||||
ExchangeMeltRequest,
|
ExchangeMeltRequest,
|
||||||
ExchangeProtocolVersion,
|
ExchangeProtocolVersion, ExchangeRefreshRevealRequest, fnutil, getRandomBytes,
|
||||||
ExchangeRefreshRevealRequest,
|
|
||||||
getRandomBytes,
|
|
||||||
HashCodeString,
|
HashCodeString,
|
||||||
HttpStatusCode,
|
HttpStatusCode,
|
||||||
j2s,
|
j2s, Logger, NotificationType,
|
||||||
TalerProtocolTimestamp,
|
RefreshGroupId,
|
||||||
|
RefreshReason,
|
||||||
|
TalerErrorDetail, TalerProtocolTimestamp, URL
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import { TalerCryptoInterface } from "../crypto/cryptoImplementation.js";
|
||||||
|
import {
|
||||||
|
DerivedRefreshSession,
|
||||||
|
RefreshNewDenomInfo
|
||||||
|
} from "../crypto/cryptoTypes.js";
|
||||||
|
import { CryptoApiStoppedError } from "../crypto/workers/cryptoDispatcher.js";
|
||||||
import {
|
import {
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
@ -37,57 +45,29 @@ import {
|
|||||||
OperationStatus,
|
OperationStatus,
|
||||||
RefreshCoinStatus,
|
RefreshCoinStatus,
|
||||||
RefreshGroupRecord,
|
RefreshGroupRecord,
|
||||||
WalletStoresV1,
|
WalletStoresV1
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import {
|
import { TalerError } from "../errors.js";
|
||||||
codecForExchangeMeltResponse,
|
|
||||||
codecForExchangeRevealResponse,
|
|
||||||
CoinPublicKey,
|
|
||||||
fnutil,
|
|
||||||
NotificationType,
|
|
||||||
RefreshGroupId,
|
|
||||||
RefreshReason,
|
|
||||||
TalerErrorDetail,
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { AmountJson, Amounts } from "@gnu-taler/taler-util";
|
|
||||||
import { amountToPretty } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
|
||||||
readSuccessResponseJsonOrThrow,
|
|
||||||
readUnexpectedResponseDetails,
|
|
||||||
} from "../util/http.js";
|
|
||||||
import { checkDbInvariant } from "../util/invariants.js";
|
|
||||||
import { Logger } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
|
||||||
resetRetryInfo,
|
|
||||||
RetryInfo,
|
|
||||||
updateRetryInfoTimeout,
|
|
||||||
} from "../util/retries.js";
|
|
||||||
import {
|
|
||||||
Duration,
|
|
||||||
durationFromSpec,
|
|
||||||
durationMul,
|
|
||||||
AbsoluteTime,
|
|
||||||
URL,
|
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
|
||||||
import {
|
import {
|
||||||
DenomInfo,
|
DenomInfo,
|
||||||
EXCHANGE_COINS_LOCK,
|
EXCHANGE_COINS_LOCK,
|
||||||
InternalWalletState,
|
InternalWalletState
|
||||||
} from "../internal-wallet-state.js";
|
} from "../internal-wallet-state.js";
|
||||||
import {
|
import {
|
||||||
isWithdrawableDenom,
|
readSuccessResponseJsonOrThrow,
|
||||||
selectWithdrawalDenominations,
|
readUnexpectedResponseDetails
|
||||||
} from "./withdraw.js";
|
} from "../util/http.js";
|
||||||
import {
|
import { checkDbInvariant } from "../util/invariants.js";
|
||||||
DerivedRefreshSession,
|
|
||||||
RefreshNewDenomInfo,
|
|
||||||
} from "../crypto/cryptoTypes.js";
|
|
||||||
import { GetReadWriteAccess } from "../util/query.js";
|
import { GetReadWriteAccess } from "../util/query.js";
|
||||||
|
import {
|
||||||
|
RetryInfo
|
||||||
|
} from "../util/retries.js";
|
||||||
import { guardOperationException } from "./common.js";
|
import { guardOperationException } from "./common.js";
|
||||||
import { CryptoApiStoppedError } from "../crypto/workers/cryptoDispatcher.js";
|
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||||
import { TalerCryptoInterface } from "../crypto/cryptoImplementation.js";
|
import {
|
||||||
import { TalerError } from "../errors.js";
|
isWithdrawableDenom,
|
||||||
|
selectWithdrawalDenominations
|
||||||
|
} from "./withdraw.js";
|
||||||
|
|
||||||
const logger = new Logger("refresh.ts");
|
const logger = new Logger("refresh.ts");
|
||||||
|
|
||||||
@ -129,22 +109,22 @@ export function getTotalRefreshCost(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateGroupStatus(rg: RefreshGroupRecord): void {
|
function updateGroupStatus(rg: RefreshGroupRecord): void {
|
||||||
let allDone = fnutil.all(
|
const allDone = fnutil.all(
|
||||||
rg.statusPerCoin,
|
rg.statusPerCoin,
|
||||||
(x) => x === RefreshCoinStatus.Finished || x === RefreshCoinStatus.Frozen,
|
(x) => x === RefreshCoinStatus.Finished || x === RefreshCoinStatus.Frozen,
|
||||||
);
|
);
|
||||||
let anyFrozen = fnutil.any(
|
const anyFrozen = fnutil.any(
|
||||||
rg.statusPerCoin,
|
rg.statusPerCoin,
|
||||||
(x) => x === RefreshCoinStatus.Frozen,
|
(x) => x === RefreshCoinStatus.Frozen,
|
||||||
);
|
);
|
||||||
if (allDone) {
|
if (allDone) {
|
||||||
if (anyFrozen) {
|
if (anyFrozen) {
|
||||||
rg.frozen = true;
|
rg.frozen = true;
|
||||||
rg.retryInfo = resetRetryInfo();
|
rg.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
rg.timestampFinished = AbsoluteTime.toTimestamp(AbsoluteTime.now());
|
rg.timestampFinished = AbsoluteTime.toTimestamp(AbsoluteTime.now());
|
||||||
rg.operationStatus = OperationStatus.Finished;
|
rg.operationStatus = OperationStatus.Finished;
|
||||||
rg.retryInfo = resetRetryInfo();
|
rg.retryInfo = RetryInfo.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,7 +733,7 @@ async function setupRefreshRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
||||||
}
|
}
|
||||||
@ -987,7 +967,7 @@ export async function createRefreshGroup(
|
|||||||
reason,
|
reason,
|
||||||
refreshGroupId,
|
refreshGroupId,
|
||||||
refreshSessionPerCoin: oldCoinPubs.map(() => undefined),
|
refreshSessionPerCoin: oldCoinPubs.map(() => undefined),
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
inputPerCoin,
|
inputPerCoin,
|
||||||
estimatedOutputPerCoin,
|
estimatedOutputPerCoin,
|
||||||
timestampCreated: TalerProtocolTimestamp.now(),
|
timestampCreated: TalerProtocolTimestamp.now(),
|
||||||
|
@ -25,29 +25,18 @@
|
|||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
AbortingCoin,
|
AbortingCoin,
|
||||||
AbortRequest,
|
AbortRequest, AbsoluteTime, AmountJson,
|
||||||
AmountJson,
|
|
||||||
Amounts,
|
Amounts,
|
||||||
ApplyRefundResponse,
|
ApplyRefundResponse,
|
||||||
codecForAbortResponse,
|
codecForAbortResponse,
|
||||||
codecForMerchantOrderRefundPickupResponse,
|
codecForMerchantOrderRefundPickupResponse, codecForMerchantOrderStatusPaid, CoinPublicKey, Duration, Logger,
|
||||||
CoinPublicKey,
|
|
||||||
Logger,
|
|
||||||
MerchantCoinRefundFailureStatus,
|
MerchantCoinRefundFailureStatus,
|
||||||
MerchantCoinRefundStatus,
|
MerchantCoinRefundStatus,
|
||||||
MerchantCoinRefundSuccessStatus,
|
MerchantCoinRefundSuccessStatus,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
parseRefundUri,
|
parseRefundUri, PrepareRefundResult, RefreshReason,
|
||||||
RefreshReason,
|
|
||||||
TalerErrorCode,
|
TalerErrorCode,
|
||||||
TalerErrorDetail,
|
TalerErrorDetail, TalerProtocolTimestamp, URL
|
||||||
URL,
|
|
||||||
codecForMerchantOrderStatusPaid,
|
|
||||||
AbsoluteTime,
|
|
||||||
TalerProtocolTimestamp,
|
|
||||||
Duration,
|
|
||||||
PrepareRefundRequest,
|
|
||||||
PrepareRefundResult,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
AbortStatus,
|
AbortStatus,
|
||||||
@ -55,19 +44,17 @@ import {
|
|||||||
PurchaseRecord,
|
PurchaseRecord,
|
||||||
RefundReason,
|
RefundReason,
|
||||||
RefundState,
|
RefundState,
|
||||||
WalletStoresV1,
|
WalletStoresV1
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
||||||
import { checkDbInvariant } from "../util/invariants.js";
|
import { checkDbInvariant } from "../util/invariants.js";
|
||||||
import { GetReadWriteAccess } from "../util/query.js";
|
import { GetReadWriteAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
resetRetryInfo,
|
RetryInfo
|
||||||
RetryInfo,
|
|
||||||
updateRetryInfoTimeout,
|
|
||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
|
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
|
||||||
import { guardOperationException } from "./common.js";
|
import { guardOperationException } from "./common.js";
|
||||||
|
import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
|
||||||
|
|
||||||
const logger = new Logger("refund.ts");
|
const logger = new Logger("refund.ts");
|
||||||
|
|
||||||
@ -147,7 +134,7 @@ async function setupPurchaseQueryRefundRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
pr.refundStatusRetryInfo = resetRetryInfo();
|
pr.refundStatusRetryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
pr.refundStatusRetryInfo = RetryInfo.increment(
|
pr.refundStatusRetryInfo = RetryInfo.increment(
|
||||||
pr.refundStatusRetryInfo,
|
pr.refundStatusRetryInfo,
|
||||||
@ -500,7 +487,7 @@ async function acceptRefunds(
|
|||||||
if (queryDone) {
|
if (queryDone) {
|
||||||
p.timestampLastRefundStatus = now;
|
p.timestampLastRefundStatus = now;
|
||||||
p.lastRefundStatusError = undefined;
|
p.lastRefundStatusError = undefined;
|
||||||
p.refundStatusRetryInfo = resetRetryInfo();
|
p.refundStatusRetryInfo = RetryInfo.reset();
|
||||||
p.refundQueryRequested = false;
|
p.refundQueryRequested = false;
|
||||||
if (p.abortStatus === AbortStatus.AbortRefund) {
|
if (p.abortStatus === AbortStatus.AbortRefund) {
|
||||||
p.abortStatus = AbortStatus.AbortFinished;
|
p.abortStatus = AbortStatus.AbortFinished;
|
||||||
@ -509,8 +496,7 @@ async function acceptRefunds(
|
|||||||
} else {
|
} else {
|
||||||
// No error, but we need to try again!
|
// No error, but we need to try again!
|
||||||
p.timestampLastRefundStatus = now;
|
p.timestampLastRefundStatus = now;
|
||||||
p.refundStatusRetryInfo.retryCounter++;
|
p.refundStatusRetryInfo = RetryInfo.increment(p.refundStatusRetryInfo)
|
||||||
updateRetryInfoTimeout(p.refundStatusRetryInfo);
|
|
||||||
p.lastRefundStatusError = undefined;
|
p.lastRefundStatusError = undefined;
|
||||||
logger.trace("refund query not done");
|
logger.trace("refund query not done");
|
||||||
}
|
}
|
||||||
@ -619,7 +605,7 @@ export async function applyRefund(
|
|||||||
}
|
}
|
||||||
p.refundQueryRequested = true;
|
p.refundQueryRequested = true;
|
||||||
p.lastRefundStatusError = undefined;
|
p.lastRefundStatusError = undefined;
|
||||||
p.refundStatusRetryInfo = resetRetryInfo();
|
p.refundStatusRetryInfo = RetryInfo.reset();
|
||||||
await tx.purchases.put(p);
|
await tx.purchases.put(p);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -892,7 +878,7 @@ export async function abortFailedPayWithRefund(
|
|||||||
purchase.paymentSubmitPending = false;
|
purchase.paymentSubmitPending = false;
|
||||||
purchase.abortStatus = AbortStatus.AbortRefund;
|
purchase.abortStatus = AbortStatus.AbortRefund;
|
||||||
purchase.lastPayError = undefined;
|
purchase.lastPayError = undefined;
|
||||||
purchase.payRetryInfo = resetRetryInfo();
|
purchase.payRetryInfo = RetryInfo.reset();
|
||||||
await tx.purchases.put(purchase);
|
await tx.purchases.put(purchase);
|
||||||
});
|
});
|
||||||
processPurchaseQueryRefund(ws, proposalId, {
|
processPurchaseQueryRefund(ws, proposalId, {
|
||||||
|
@ -58,8 +58,6 @@ import {
|
|||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { GetReadOnlyAccess } from "../util/query.js";
|
import { GetReadOnlyAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
getRetryDuration,
|
|
||||||
resetRetryInfo,
|
|
||||||
RetryInfo,
|
RetryInfo,
|
||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
import {
|
import {
|
||||||
@ -100,7 +98,7 @@ async function setupReserveRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
r.retryInfo = RetryInfo.increment(r.retryInfo);
|
||||||
}
|
}
|
||||||
@ -196,7 +194,7 @@ export async function createReserve(
|
|||||||
timestampReserveInfoPosted: undefined,
|
timestampReserveInfoPosted: undefined,
|
||||||
bankInfo,
|
bankInfo,
|
||||||
reserveStatus,
|
reserveStatus,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
currency: req.amount.currency,
|
currency: req.amount.currency,
|
||||||
operationStatus: OperationStatus.Pending,
|
operationStatus: OperationStatus.Pending,
|
||||||
@ -297,7 +295,7 @@ export async function forceQueryReserve(
|
|||||||
case ReserveRecordStatus.Dormant:
|
case ReserveRecordStatus.Dormant:
|
||||||
reserve.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
reserve.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
||||||
reserve.operationStatus = OperationStatus.Pending;
|
reserve.operationStatus = OperationStatus.Pending;
|
||||||
reserve.retryInfo = resetRetryInfo();
|
reserve.retryInfo = RetryInfo.reset();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -392,7 +390,7 @@ async function registerReserveWithBank(
|
|||||||
if (!r.bankInfo) {
|
if (!r.bankInfo) {
|
||||||
throw Error("invariant failed");
|
throw Error("invariant failed");
|
||||||
}
|
}
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
await tx.reserves.put(r);
|
await tx.reserves.put(r);
|
||||||
});
|
});
|
||||||
ws.notify({ type: NotificationType.ReserveRegisteredWithBank });
|
ws.notify({ type: NotificationType.ReserveRegisteredWithBank });
|
||||||
@ -402,7 +400,7 @@ async function registerReserveWithBank(
|
|||||||
export function getReserveRequestTimeout(r: ReserveRecord): Duration {
|
export function getReserveRequestTimeout(r: ReserveRecord): Duration {
|
||||||
return durationMax(
|
return durationMax(
|
||||||
{ d_ms: 60000 },
|
{ d_ms: 60000 },
|
||||||
durationMin({ d_ms: 5000 }, getRetryDuration(r.retryInfo)),
|
durationMin({ d_ms: 5000 }, RetryInfo.getDuration(r.retryInfo)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +457,7 @@ async function processReserveBankStatus(
|
|||||||
r.timestampBankConfirmed = now;
|
r.timestampBankConfirmed = now;
|
||||||
r.reserveStatus = ReserveRecordStatus.BankAborted;
|
r.reserveStatus = ReserveRecordStatus.BankAborted;
|
||||||
r.operationStatus = OperationStatus.Finished;
|
r.operationStatus = OperationStatus.Finished;
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
await tx.reserves.put(r);
|
await tx.reserves.put(r);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -496,7 +494,7 @@ async function processReserveBankStatus(
|
|||||||
r.timestampBankConfirmed = now;
|
r.timestampBankConfirmed = now;
|
||||||
r.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
r.reserveStatus = ReserveRecordStatus.QueryingStatus;
|
||||||
r.operationStatus = OperationStatus.Pending;
|
r.operationStatus = OperationStatus.Pending;
|
||||||
r.retryInfo = resetRetryInfo();
|
r.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
switch (r.reserveStatus) {
|
switch (r.reserveStatus) {
|
||||||
case ReserveRecordStatus.WaitConfirmBank:
|
case ReserveRecordStatus.WaitConfirmBank:
|
||||||
@ -662,7 +660,7 @@ async function updateReserve(
|
|||||||
reservePub: reserve.reservePub,
|
reservePub: reserve.reservePub,
|
||||||
rawWithdrawalAmount: remainingAmount,
|
rawWithdrawalAmount: remainingAmount,
|
||||||
timestampStart: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
|
timestampStart: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
denomsSel: denomSel,
|
denomsSel: denomSel,
|
||||||
secretSeed: encodeCrock(getRandomBytes(64)),
|
secretSeed: encodeCrock(getRandomBytes(64)),
|
||||||
@ -721,12 +719,13 @@ async function processReserveImpl(
|
|||||||
case ReserveRecordStatus.RegisteringBank:
|
case ReserveRecordStatus.RegisteringBank:
|
||||||
await processReserveBankStatus(ws, reservePub);
|
await processReserveBankStatus(ws, reservePub);
|
||||||
return await processReserveImpl(ws, reservePub, { forceNow: true });
|
return await processReserveImpl(ws, reservePub, { forceNow: true });
|
||||||
case ReserveRecordStatus.QueryingStatus:
|
case ReserveRecordStatus.QueryingStatus: {
|
||||||
const res = await updateReserve(ws, reservePub);
|
const res = await updateReserve(ws, reservePub);
|
||||||
if (res.ready) {
|
if (res.ready) {
|
||||||
return await processReserveImpl(ws, reservePub, { forceNow: true });
|
return await processReserveImpl(ws, reservePub, { forceNow: true });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ReserveRecordStatus.Dormant:
|
case ReserveRecordStatus.Dormant:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
break;
|
break;
|
||||||
|
@ -18,51 +18,30 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
PrepareTipResult,
|
Amounts, BlindedDenominationSignature,
|
||||||
parseTipUri,
|
codecForMerchantTipResponseV2, codecForTipPickupGetResponse, DenomKeyType, encodeCrock, getRandomBytes, j2s, Logger, NotificationType, parseTipUri, PrepareTipResult, TalerErrorCode, TalerErrorDetail, TalerProtocolTimestamp, TipPlanchetDetail, URL
|
||||||
codecForTipPickupGetResponse,
|
|
||||||
Amounts,
|
|
||||||
TalerErrorDetail,
|
|
||||||
NotificationType,
|
|
||||||
TipPlanchetDetail,
|
|
||||||
TalerErrorCode,
|
|
||||||
Logger,
|
|
||||||
URL,
|
|
||||||
DenomKeyType,
|
|
||||||
BlindedDenominationSignature,
|
|
||||||
codecForMerchantTipResponseV2,
|
|
||||||
TalerProtocolTimestamp,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { DerivedTipPlanchet } from "../crypto/cryptoTypes.js";
|
import { DerivedTipPlanchet } from "../crypto/cryptoTypes.js";
|
||||||
import {
|
import {
|
||||||
DenominationRecord,
|
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
CoinStatus,
|
CoinStatus, DenominationRecord, TipRecord
|
||||||
TipRecord,
|
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { j2s } from "@gnu-taler/taler-util";
|
|
||||||
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
|
|
||||||
import {
|
|
||||||
resetRetryInfo,
|
|
||||||
RetryInfo,
|
|
||||||
updateRetryInfoTimeout,
|
|
||||||
} from "../util/retries.js";
|
|
||||||
import { makeErrorDetail } from "../errors.js";
|
import { makeErrorDetail } from "../errors.js";
|
||||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import {
|
|
||||||
getExchangeWithdrawalInfo,
|
|
||||||
updateWithdrawalDenoms,
|
|
||||||
getCandidateWithdrawalDenoms,
|
|
||||||
selectWithdrawalDenominations,
|
|
||||||
} from "./withdraw.js";
|
|
||||||
import {
|
import {
|
||||||
getHttpResponseErrorDetails,
|
getHttpResponseErrorDetails,
|
||||||
readSuccessResponseJsonOrThrow,
|
readSuccessResponseJsonOrThrow
|
||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { encodeCrock, getRandomBytes } from "@gnu-taler/taler-util";
|
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
|
||||||
|
import {
|
||||||
|
RetryInfo
|
||||||
|
} from "../util/retries.js";
|
||||||
import { guardOperationException } from "./common.js";
|
import { guardOperationException } from "./common.js";
|
||||||
|
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||||
|
import {
|
||||||
|
getCandidateWithdrawalDenoms, getExchangeWithdrawalInfo, selectWithdrawalDenominations, updateWithdrawalDenoms
|
||||||
|
} from "./withdraw.js";
|
||||||
|
|
||||||
const logger = new Logger("operations/tip.ts");
|
const logger = new Logger("operations/tip.ts");
|
||||||
|
|
||||||
@ -130,7 +109,7 @@ export async function prepareTip(
|
|||||||
createdTimestamp: TalerProtocolTimestamp.now(),
|
createdTimestamp: TalerProtocolTimestamp.now(),
|
||||||
merchantTipId: res.merchantTipId,
|
merchantTipId: res.merchantTipId,
|
||||||
tipAmountEffective: selectedDenoms.totalCoinValue,
|
tipAmountEffective: selectedDenoms.totalCoinValue,
|
||||||
retryInfo: resetRetryInfo(),
|
retryInfo: RetryInfo.reset(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
denomsSel: selectedDenoms,
|
denomsSel: selectedDenoms,
|
||||||
pickedUpTimestamp: undefined,
|
pickedUpTimestamp: undefined,
|
||||||
@ -202,7 +181,7 @@ async function setupTipRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
t.retryInfo = resetRetryInfo();
|
t.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
t.retryInfo = RetryInfo.increment(t.retryInfo);
|
t.retryInfo = RetryInfo.increment(t.retryInfo);
|
||||||
}
|
}
|
||||||
@ -237,7 +216,7 @@ async function resetTipRetry(
|
|||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
const x = await tx.tips.get(tipId);
|
const x = await tx.tips.get(tipId);
|
||||||
if (x) {
|
if (x) {
|
||||||
x.retryInfo = resetRetryInfo();
|
x.retryInfo = RetryInfo.reset();
|
||||||
await tx.tips.put(x);
|
await tx.tips.put(x);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -430,7 +409,7 @@ async function processTipImpl(
|
|||||||
}
|
}
|
||||||
tr.pickedUpTimestamp = TalerProtocolTimestamp.now();
|
tr.pickedUpTimestamp = TalerProtocolTimestamp.now();
|
||||||
tr.lastError = undefined;
|
tr.lastError = undefined;
|
||||||
tr.retryInfo = resetRetryInfo();
|
tr.retryInfo = RetryInfo.reset();
|
||||||
await tx.tips.put(tr);
|
await tx.tips.put(tr);
|
||||||
for (const cr of newCoinRecords) {
|
for (const cr of newCoinRecords) {
|
||||||
await tx.coins.put(cr);
|
await tx.coins.put(cr);
|
||||||
|
@ -72,7 +72,7 @@ import {
|
|||||||
readSuccessResponseJsonOrThrow,
|
readSuccessResponseJsonOrThrow,
|
||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
|
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
|
||||||
import { resetRetryInfo, RetryInfo } from "../util/retries.js";
|
import { RetryInfo } from "../util/retries.js";
|
||||||
import {
|
import {
|
||||||
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
|
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
|
||||||
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
@ -875,11 +875,10 @@ export async function updateWithdrawalDenoms(
|
|||||||
denom.verificationStatus === DenominationVerificationStatus.Unverified
|
denom.verificationStatus === DenominationVerificationStatus.Unverified
|
||||||
) {
|
) {
|
||||||
logger.trace(
|
logger.trace(
|
||||||
`Validating denomination (${current + 1}/${
|
`Validating denomination (${current + 1}/${denominations.length
|
||||||
denominations.length
|
|
||||||
}) signature of ${denom.denomPubHash}`,
|
}) signature of ${denom.denomPubHash}`,
|
||||||
);
|
);
|
||||||
let valid: boolean = false;
|
let valid = false;
|
||||||
if (ws.insecureTrustExchange) {
|
if (ws.insecureTrustExchange) {
|
||||||
valid = true;
|
valid = true;
|
||||||
} else {
|
} else {
|
||||||
@ -932,7 +931,7 @@ async function setupWithdrawalRetry(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.reset) {
|
if (options.reset) {
|
||||||
wsr.retryInfo = resetRetryInfo();
|
wsr.retryInfo = RetryInfo.reset();
|
||||||
} else {
|
} else {
|
||||||
wsr.retryInfo = RetryInfo.increment(wsr.retryInfo);
|
wsr.retryInfo = RetryInfo.increment(wsr.retryInfo);
|
||||||
}
|
}
|
||||||
@ -1097,7 +1096,7 @@ async function processWithdrawGroupImpl(
|
|||||||
wg.timestampFinish = TalerProtocolTimestamp.now();
|
wg.timestampFinish = TalerProtocolTimestamp.now();
|
||||||
wg.operationStatus = OperationStatus.Finished;
|
wg.operationStatus = OperationStatus.Finished;
|
||||||
delete wg.lastError;
|
delete wg.lastError;
|
||||||
wg.retryInfo = resetRetryInfo();
|
wg.retryInfo = RetryInfo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
await tx.withdrawalGroups.put(wg);
|
await tx.withdrawalGroups.put(wg);
|
||||||
|
@ -41,7 +41,7 @@ const defaultRetryPolicy: RetryPolicy = {
|
|||||||
maxTimeout: { d_ms: 6000 },
|
maxTimeout: { d_ms: 6000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function updateRetryInfoTimeout(
|
function updateTimeout(
|
||||||
r: RetryInfo,
|
r: RetryInfo,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
): void {
|
): void {
|
||||||
@ -65,7 +65,9 @@ export function updateRetryInfoTimeout(
|
|||||||
r.nextRetry = { t_ms: t };
|
r.nextRetry = { t_ms: t };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRetryDuration(
|
export namespace RetryInfo {
|
||||||
|
|
||||||
|
export function getDuration(
|
||||||
r: RetryInfo | undefined,
|
r: RetryInfo | undefined,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
): Duration {
|
): Duration {
|
||||||
@ -82,28 +84,27 @@ export function getRetryDuration(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetRetryInfo(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
|
export function reset(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
|
||||||
const now = AbsoluteTime.now();
|
const now = AbsoluteTime.now();
|
||||||
const info = {
|
const info = {
|
||||||
firstTry: now,
|
firstTry: now,
|
||||||
nextRetry: now,
|
nextRetry: now,
|
||||||
retryCounter: 0,
|
retryCounter: 0,
|
||||||
};
|
};
|
||||||
updateRetryInfoTimeout(info, p);
|
updateTimeout(info, p);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace RetryInfo {
|
|
||||||
export function increment(
|
export function increment(
|
||||||
r: RetryInfo | undefined,
|
r: RetryInfo | undefined,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
) {
|
): RetryInfo {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return resetRetryInfo(p);
|
return reset(p);
|
||||||
}
|
}
|
||||||
const r2 = { ...r };
|
const r2 = { ...r };
|
||||||
r2.retryCounter++;
|
r2.retryCounter++;
|
||||||
updateRetryInfoTimeout(r2, p);
|
updateTimeout(r2, p);
|
||||||
return r2;
|
return r2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,6 +335,7 @@ async function runTaskLoop(
|
|||||||
let numGivingLiveness = 0;
|
let numGivingLiveness = 0;
|
||||||
let numDue = 0;
|
let numDue = 0;
|
||||||
let minDue: AbsoluteTime = AbsoluteTime.never();
|
let minDue: AbsoluteTime = AbsoluteTime.never();
|
||||||
|
|
||||||
for (const p of pending.pendingOperations) {
|
for (const p of pending.pendingOperations) {
|
||||||
minDue = AbsoluteTime.min(minDue, p.timestampDue);
|
minDue = AbsoluteTime.min(minDue, p.timestampDue);
|
||||||
if (AbsoluteTime.isExpired(p.timestampDue)) {
|
if (AbsoluteTime.isExpired(p.timestampDue)) {
|
||||||
@ -683,9 +684,13 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
|
|||||||
c.exchangeBaseUrl,
|
c.exchangeBaseUrl,
|
||||||
c.denomPubHash,
|
c.denomPubHash,
|
||||||
);
|
);
|
||||||
|
if (!denomInfo) {
|
||||||
|
console.error("no denomination found for coin")
|
||||||
|
continue;
|
||||||
|
}
|
||||||
coinsJson.coins.push({
|
coinsJson.coins.push({
|
||||||
coin_pub: c.coinPub,
|
coin_pub: c.coinPub,
|
||||||
denom_pub: denomInfo?.denomPub!,
|
denom_pub: denomInfo.denomPub,
|
||||||
denom_pub_hash: c.denomPubHash,
|
denom_pub_hash: c.denomPubHash,
|
||||||
denom_value: Amounts.stringify(denom.value),
|
denom_value: Amounts.stringify(denom.value),
|
||||||
exchange_base_url: c.exchangeBaseUrl,
|
exchange_base_url: c.exchangeBaseUrl,
|
||||||
|
Loading…
Reference in New Issue
Block a user