wallet-core: towards DD48
This commit is contained in:
parent
88f7338d7c
commit
d19aef746c
@ -312,6 +312,14 @@ export namespace Duration {
|
||||
}
|
||||
|
||||
export namespace AbsoluteTime {
|
||||
export function getStampMsNow(): number {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
export function getStampMsNever(): number {
|
||||
return Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
|
||||
export function now(): AbsoluteTime {
|
||||
return {
|
||||
t_ms: new Date().getTime() + timeshift,
|
||||
@ -398,6 +406,13 @@ export namespace AbsoluteTime {
|
||||
};
|
||||
}
|
||||
|
||||
export function fromStampMs(stampMs: number): AbsoluteTime {
|
||||
return {
|
||||
t_ms: stampMs,
|
||||
[opaque_AbsoluteTime]: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromPreciseTimestamp(t: TalerPreciseTimestamp): AbsoluteTime {
|
||||
if (t.t_s === "never") {
|
||||
return { t_ms: "never", [opaque_AbsoluteTime]: true };
|
||||
@ -409,6 +424,13 @@ export namespace AbsoluteTime {
|
||||
};
|
||||
}
|
||||
|
||||
export function toStampMs(at: AbsoluteTime): number {
|
||||
if (at.t_ms === "never") {
|
||||
return Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
return at.t_ms;
|
||||
}
|
||||
|
||||
export function toPreciseTimestamp(at: AbsoluteTime): TalerPreciseTimestamp {
|
||||
if (at.t_ms == "never") {
|
||||
return {
|
||||
|
@ -1262,17 +1262,25 @@ export interface ExchangeFullDetails {
|
||||
}
|
||||
|
||||
export enum ExchangeTosStatus {
|
||||
New = "new",
|
||||
Pending = "pending",
|
||||
Proposed = "proposed",
|
||||
Accepted = "accepted",
|
||||
Changed = "changed",
|
||||
NotFound = "not-found",
|
||||
Unknown = "unknown",
|
||||
}
|
||||
|
||||
export enum ExchangeEntryStatus {
|
||||
Unknown = "unknown",
|
||||
Outdated = "outdated",
|
||||
Ok = "ok",
|
||||
Preset = "preset",
|
||||
Ephemeral = "ephemeral",
|
||||
Used = "used",
|
||||
}
|
||||
|
||||
export enum ExchangeUpdateStatus {
|
||||
Initial = "initial",
|
||||
InitialUpdate = "initial(update)",
|
||||
Suspended = "suspended",
|
||||
Failed = "failed",
|
||||
OutdatedUpdate = "outdated(update)",
|
||||
Ready = "ready",
|
||||
ReadyUpdate = "ready(update)",
|
||||
}
|
||||
|
||||
export interface OperationErrorInfo {
|
||||
@ -1285,13 +1293,9 @@ export interface ExchangeListItem {
|
||||
currency: string | undefined;
|
||||
paytoUris: string[];
|
||||
tosStatus: ExchangeTosStatus;
|
||||
exchangeStatus: ExchangeEntryStatus;
|
||||
exchangeEntryStatus: ExchangeEntryStatus;
|
||||
exchangeUpdateStatus: ExchangeUpdateStatus;
|
||||
ageRestrictionOptions: number[];
|
||||
/**
|
||||
* Permanently added to the wallet, as opposed to just
|
||||
* temporarily queried.
|
||||
*/
|
||||
permanent: boolean;
|
||||
|
||||
/**
|
||||
* Information about the last error that occurred when trying
|
||||
@ -1370,8 +1374,8 @@ export const codecForExchangeListItem = (): Codec<ExchangeListItem> =>
|
||||
.property("exchangeBaseUrl", codecForString())
|
||||
.property("paytoUris", codecForList(codecForString()))
|
||||
.property("tosStatus", codecForAny())
|
||||
.property("exchangeStatus", codecForAny())
|
||||
.property("permanent", codecForBoolean())
|
||||
.property("exchangeEntryStatus", codecForAny())
|
||||
.property("exchangeUpdateStatus", codecForAny())
|
||||
.property("ageRestrictionOptions", codecForList(codecForNumber()))
|
||||
.build("ExchangeListItem");
|
||||
|
||||
|
@ -42,7 +42,7 @@ import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
|
||||
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
||||
import {
|
||||
ExchangeDetailsRecord,
|
||||
ExchangeRecord,
|
||||
ExchangeEntryRecord,
|
||||
RefreshReasonDetails,
|
||||
WalletStoresV1,
|
||||
} from "./db.js";
|
||||
@ -108,7 +108,7 @@ export interface ExchangeOperations {
|
||||
): Promise<ExchangeDetailsRecord | undefined>;
|
||||
getExchangeTrust(
|
||||
ws: InternalWalletState,
|
||||
exchangeInfo: ExchangeRecord,
|
||||
exchangeInfo: ExchangeEntryRecord,
|
||||
): Promise<TrustInfo>;
|
||||
updateExchangeFromUrl(
|
||||
ws: InternalWalletState,
|
||||
@ -118,7 +118,7 @@ export interface ExchangeOperations {
|
||||
cancellationToken?: CancellationToken;
|
||||
},
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
exchange: ExchangeEntryRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord;
|
||||
}>;
|
||||
}
|
||||
|
@ -342,20 +342,19 @@ export async function importBackup(
|
||||
if (existingExchange) {
|
||||
continue;
|
||||
}
|
||||
await tx.exchanges.put({
|
||||
baseUrl: backupExchange.base_url,
|
||||
detailsPointer: {
|
||||
currency: backupExchange.currency,
|
||||
masterPublicKey: backupExchange.master_public_key,
|
||||
updateClock: backupExchange.update_clock,
|
||||
},
|
||||
permanent: true,
|
||||
lastUpdate: undefined,
|
||||
nextUpdate: TalerPreciseTimestamp.now(),
|
||||
nextRefreshCheck: TalerPreciseTimestamp.now(),
|
||||
lastKeysEtag: undefined,
|
||||
lastWireEtag: undefined,
|
||||
});
|
||||
// await tx.exchanges.put({
|
||||
// baseUrl: backupExchange.base_url,
|
||||
// detailsPointer: {
|
||||
// currency: backupExchange.currency,
|
||||
// masterPublicKey: backupExchange.master_public_key,
|
||||
// updateClock: backupExchange.update_clock,
|
||||
// },
|
||||
// lastUpdate: undefined,
|
||||
// nextUpdate: TalerPreciseTimestamp.now(),
|
||||
// nextRefreshCheck: TalerPreciseTimestamp.now(),
|
||||
// lastKeysEtag: undefined,
|
||||
// lastWireEtag: undefined,
|
||||
// });
|
||||
}
|
||||
|
||||
for (const backupExchangeDetails of backupBlob.exchange_details) {
|
||||
|
@ -30,6 +30,7 @@ import {
|
||||
ExchangeEntryStatus,
|
||||
ExchangeListItem,
|
||||
ExchangeTosStatus,
|
||||
ExchangeUpdateStatus,
|
||||
getErrorDetailFromException,
|
||||
j2s,
|
||||
Logger,
|
||||
@ -47,7 +48,7 @@ import {
|
||||
WalletStoresV1,
|
||||
CoinRecord,
|
||||
ExchangeDetailsRecord,
|
||||
ExchangeRecord,
|
||||
ExchangeEntryRecord,
|
||||
BackupProviderRecord,
|
||||
DepositGroupRecord,
|
||||
PeerPullPaymentIncomingRecord,
|
||||
@ -59,6 +60,8 @@ import {
|
||||
RefreshGroupRecord,
|
||||
RewardRecord,
|
||||
WithdrawalGroupRecord,
|
||||
ExchangeEntryDbUpdateStatus,
|
||||
ExchangeEntryDbRecordStatus,
|
||||
} from "../db.js";
|
||||
import { makeErrorDetail, TalerError } from "@gnu-taler/taler-util";
|
||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||
@ -529,16 +532,16 @@ export function getExchangeTosStatus(
|
||||
exchangeDetails: ExchangeDetailsRecord,
|
||||
): ExchangeTosStatus {
|
||||
if (!exchangeDetails.tosAccepted) {
|
||||
return ExchangeTosStatus.New;
|
||||
return ExchangeTosStatus.Proposed;
|
||||
}
|
||||
if (exchangeDetails.tosAccepted?.etag == exchangeDetails.tosCurrentEtag) {
|
||||
return ExchangeTosStatus.Accepted;
|
||||
}
|
||||
return ExchangeTosStatus.Changed;
|
||||
return ExchangeTosStatus.Proposed;
|
||||
}
|
||||
|
||||
export function makeExchangeListItem(
|
||||
r: ExchangeRecord,
|
||||
r: ExchangeEntryRecord,
|
||||
exchangeDetails: ExchangeDetailsRecord | undefined,
|
||||
lastError: TalerErrorDetail | undefined,
|
||||
): ExchangeListItem {
|
||||
@ -547,30 +550,57 @@ export function makeExchangeListItem(
|
||||
error: lastError,
|
||||
}
|
||||
: undefined;
|
||||
if (!exchangeDetails) {
|
||||
return {
|
||||
exchangeBaseUrl: r.baseUrl,
|
||||
currency: undefined,
|
||||
tosStatus: ExchangeTosStatus.Unknown,
|
||||
paytoUris: [],
|
||||
exchangeStatus: ExchangeEntryStatus.Unknown,
|
||||
permanent: r.permanent,
|
||||
ageRestrictionOptions: [],
|
||||
lastUpdateErrorInfo,
|
||||
};
|
||||
|
||||
let exchangeUpdateStatus: ExchangeUpdateStatus;
|
||||
switch (r.updateStatus) {
|
||||
case ExchangeEntryDbUpdateStatus.Failed:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.Failed;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.Initial:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.Initial;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.InitialUpdate:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.InitialUpdate;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.OutdatedUpdate:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.OutdatedUpdate;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.Ready:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.Ready;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.ReadyUpdate:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.ReadyUpdate;
|
||||
break;
|
||||
case ExchangeEntryDbUpdateStatus.Suspended:
|
||||
exchangeUpdateStatus = ExchangeUpdateStatus.Suspended;
|
||||
break;
|
||||
}
|
||||
let exchangeStatus;
|
||||
exchangeStatus = ExchangeEntryStatus.Ok;
|
||||
|
||||
let exchangeEntryStatus: ExchangeEntryStatus;
|
||||
switch (r.entryStatus) {
|
||||
case ExchangeEntryDbRecordStatus.Ephemeral:
|
||||
exchangeEntryStatus = ExchangeEntryStatus.Ephemeral;
|
||||
break;
|
||||
case ExchangeEntryDbRecordStatus.Preset:
|
||||
exchangeEntryStatus = ExchangeEntryStatus.Preset;
|
||||
break;
|
||||
case ExchangeEntryDbRecordStatus.Used:
|
||||
exchangeEntryStatus = ExchangeEntryStatus.Used;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
exchangeBaseUrl: r.baseUrl,
|
||||
currency: exchangeDetails.currency,
|
||||
tosStatus: getExchangeTosStatus(exchangeDetails),
|
||||
paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri),
|
||||
exchangeStatus,
|
||||
permanent: r.permanent,
|
||||
ageRestrictionOptions: exchangeDetails.ageMask
|
||||
currency: exchangeDetails?.currency,
|
||||
exchangeUpdateStatus,
|
||||
exchangeEntryStatus,
|
||||
tosStatus: exchangeDetails
|
||||
? getExchangeTosStatus(exchangeDetails)
|
||||
: ExchangeTosStatus.Pending,
|
||||
ageRestrictionOptions: exchangeDetails?.ageMask
|
||||
? AgeRestriction.getAgeGroupsFromMask(exchangeDetails.ageMask)
|
||||
: [],
|
||||
paytoUris: exchangeDetails?.wireInfo.accounts.map((x) => x.payto_uri) ?? [],
|
||||
lastUpdateErrorInfo,
|
||||
};
|
||||
}
|
||||
@ -892,13 +922,13 @@ export namespace TaskIdentifiers {
|
||||
export function forWithdrawal(wg: WithdrawalGroupRecord): TaskId {
|
||||
return `${PendingTaskType.Withdraw}:${wg.withdrawalGroupId}` as TaskId;
|
||||
}
|
||||
export function forExchangeUpdate(exch: ExchangeRecord): TaskId {
|
||||
export function forExchangeUpdate(exch: ExchangeEntryRecord): TaskId {
|
||||
return `${PendingTaskType.ExchangeUpdate}:${exch.baseUrl}` as TaskId;
|
||||
}
|
||||
export function forExchangeUpdateFromUrl(exchBaseUrl: string): TaskId {
|
||||
return `${PendingTaskType.ExchangeUpdate}:${exchBaseUrl}` as TaskId;
|
||||
}
|
||||
export function forExchangeCheckRefresh(exch: ExchangeRecord): TaskId {
|
||||
export function forExchangeCheckRefresh(exch: ExchangeEntryRecord): TaskId {
|
||||
return `${PendingTaskType.ExchangeCheckRefresh}:${exch.baseUrl}` as TaskId;
|
||||
}
|
||||
export function forTipPickup(tipRecord: RewardRecord): TaskId {
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
encodeCrock,
|
||||
ExchangeAuditor,
|
||||
ExchangeDenomination,
|
||||
ExchangeEntryStatus,
|
||||
ExchangeGlobalFees,
|
||||
ExchangeSignKeyJson,
|
||||
ExchangeWireJson,
|
||||
@ -66,10 +67,15 @@ import {
|
||||
DenominationRecord,
|
||||
DenominationVerificationStatus,
|
||||
ExchangeDetailsRecord,
|
||||
ExchangeRecord,
|
||||
ExchangeEntryRecord,
|
||||
WalletStoresV1,
|
||||
} from "../db.js";
|
||||
import { isWithdrawableDenom } from "../index.js";
|
||||
import {
|
||||
ExchangeEntryDbRecordStatus,
|
||||
ExchangeEntryDbUpdateStatus,
|
||||
isWithdrawableDenom,
|
||||
WalletDbReadWriteTransaction,
|
||||
} from "../index.js";
|
||||
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
|
||||
import { checkDbInvariant } from "../util/invariants.js";
|
||||
import {
|
||||
@ -326,6 +332,26 @@ export async function downloadExchangeInfo(
|
||||
};
|
||||
}
|
||||
|
||||
export async function addPresetExchangeEntry(
|
||||
tx: WalletDbReadWriteTransaction<"exchanges">,
|
||||
exchangeBaseUrl: string,
|
||||
): Promise<void> {
|
||||
let exchange = await tx.exchanges.get(exchangeBaseUrl);
|
||||
if (!exchange) {
|
||||
const r: ExchangeEntryRecord = {
|
||||
entryStatus: ExchangeEntryDbRecordStatus.Preset,
|
||||
updateStatus: ExchangeEntryDbUpdateStatus.Initial,
|
||||
baseUrl: exchangeBaseUrl,
|
||||
detailsPointer: undefined,
|
||||
lastUpdate: undefined,
|
||||
lastKeysEtag: undefined,
|
||||
nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
|
||||
nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
}
|
||||
}
|
||||
|
||||
export async function provideExchangeRecordInTx(
|
||||
ws: InternalWalletState,
|
||||
tx: GetReadWriteAccess<{
|
||||
@ -335,20 +361,20 @@ export async function provideExchangeRecordInTx(
|
||||
baseUrl: string,
|
||||
now: AbsoluteTime,
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
exchange: ExchangeEntryRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord | undefined;
|
||||
}> {
|
||||
let exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
const r: ExchangeRecord = {
|
||||
permanent: true,
|
||||
const r: ExchangeEntryRecord = {
|
||||
entryStatus: ExchangeEntryDbRecordStatus.Ephemeral,
|
||||
updateStatus: ExchangeEntryDbUpdateStatus.InitialUpdate,
|
||||
baseUrl: baseUrl,
|
||||
detailsPointer: undefined,
|
||||
lastUpdate: undefined,
|
||||
nextUpdate: AbsoluteTime.toPreciseTimestamp(now),
|
||||
nextRefreshCheck: AbsoluteTime.toPreciseTimestamp(now),
|
||||
nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
|
||||
nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
|
||||
lastKeysEtag: undefined,
|
||||
lastWireEtag: undefined,
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
exchange = r;
|
||||
@ -534,6 +560,10 @@ export async function downloadTosFromAcceptedFormat(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: Split this into two parts: (a) triggering the exchange
|
||||
* to be updated and (b) waiting for the update to finish.
|
||||
*/
|
||||
export async function updateExchangeFromUrl(
|
||||
ws: InternalWalletState,
|
||||
baseUrl: string,
|
||||
@ -543,7 +573,7 @@ export async function updateExchangeFromUrl(
|
||||
cancellationToken?: CancellationToken;
|
||||
} = {},
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
exchange: ExchangeEntryRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord;
|
||||
}> {
|
||||
const canonUrl = canonicalizeBaseUrl(baseUrl);
|
||||
@ -613,7 +643,7 @@ export async function updateExchangeFromUrlHandler(
|
||||
!forceNow &&
|
||||
exchangeDetails !== undefined &&
|
||||
!AbsoluteTime.isExpired(
|
||||
AbsoluteTime.fromPreciseTimestamp(exchange.nextUpdate),
|
||||
AbsoluteTime.fromStampMs(exchange.nextUpdateStampMs),
|
||||
)
|
||||
) {
|
||||
logger.trace("using existing exchange info");
|
||||
@ -755,11 +785,11 @@ export async function updateExchangeFromUrlHandler(
|
||||
newDetails.rowId = existingDetails.rowId;
|
||||
}
|
||||
r.lastUpdate = TalerPreciseTimestamp.now();
|
||||
r.nextUpdate = AbsoluteTime.toPreciseTimestamp(
|
||||
r.nextUpdateStampMs = AbsoluteTime.toStampMs(
|
||||
AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
|
||||
);
|
||||
// New denominations might be available.
|
||||
r.nextRefreshCheck = TalerPreciseTimestamp.now();
|
||||
r.nextRefreshCheckStampMs = AbsoluteTime.getStampMsNow();
|
||||
if (detailsPointerChanged) {
|
||||
r.detailsPointer = {
|
||||
currency: newDetails.currency,
|
||||
@ -948,7 +978,7 @@ export async function getExchangePaytoUri(
|
||||
*/
|
||||
export async function getExchangeTrust(
|
||||
ws: InternalWalletState,
|
||||
exchangeInfo: ExchangeRecord,
|
||||
exchangeInfo: ExchangeEntryRecord,
|
||||
): Promise<TrustInfo> {
|
||||
let isTrusted = false;
|
||||
let isAudited = false;
|
||||
|
@ -45,6 +45,7 @@ import {
|
||||
PeerPushPaymentIncomingRecord,
|
||||
RefundGroupRecord,
|
||||
RefundGroupStatus,
|
||||
ExchangeEntryDbUpdateStatus,
|
||||
} from "../db.js";
|
||||
import {
|
||||
PendingOperationsResponse,
|
||||
@ -81,19 +82,25 @@ async function gatherExchangePending(
|
||||
ws: InternalWalletState,
|
||||
tx: GetReadOnlyAccess<{
|
||||
exchanges: typeof WalletStoresV1.exchanges;
|
||||
exchangeDetails: typeof WalletStoresV1.exchangeDetails;
|
||||
operationRetries: typeof WalletStoresV1.operationRetries;
|
||||
}>,
|
||||
now: AbsoluteTime,
|
||||
resp: PendingOperationsResponse,
|
||||
): Promise<void> {
|
||||
// FIXME: We should do a range query here based on the update time.
|
||||
// FIXME: We should do a range query here based on the update time
|
||||
// and/or the entry state.
|
||||
await tx.exchanges.iter().forEachAsync(async (exch) => {
|
||||
switch (exch.updateStatus) {
|
||||
case ExchangeEntryDbUpdateStatus.Initial:
|
||||
case ExchangeEntryDbUpdateStatus.Suspended:
|
||||
case ExchangeEntryDbUpdateStatus.Failed:
|
||||
return;
|
||||
}
|
||||
const opTag = TaskIdentifiers.forExchangeUpdate(exch);
|
||||
let opr = await tx.operationRetries.get(opTag);
|
||||
const timestampDue =
|
||||
opr?.retryInfo.nextRetry ??
|
||||
AbsoluteTime.fromPreciseTimestamp(exch.nextUpdate);
|
||||
AbsoluteTime.fromStampMs(exch.nextUpdateStampMs);
|
||||
resp.pendingOperations.push({
|
||||
type: PendingTaskType.ExchangeUpdate,
|
||||
...getPendingCommon(ws, opTag, timestampDue),
|
||||
@ -108,7 +115,7 @@ async function gatherExchangePending(
|
||||
resp.pendingOperations.push({
|
||||
type: PendingTaskType.ExchangeCheckRefresh,
|
||||
...getPendingCommon(ws, opTag, timestampDue),
|
||||
timestampDue: AbsoluteTime.fromPreciseTimestamp(exch.nextRefreshCheck),
|
||||
timestampDue: AbsoluteTime.fromStampMs(exch.nextRefreshCheckStampMs),
|
||||
givesLifeness: false,
|
||||
exchangeBaseUrl: exch.baseUrl,
|
||||
});
|
||||
@ -184,8 +191,9 @@ export async function iterRecordsForWithdrawal(
|
||||
WithdrawalGroupStatus.PendingRegisteringBank,
|
||||
WithdrawalGroupStatus.PendingAml,
|
||||
);
|
||||
withdrawalGroupRecords =
|
||||
await tx.withdrawalGroups.indexes.byStatus.getAll(range);
|
||||
withdrawalGroupRecords = await tx.withdrawalGroups.indexes.byStatus.getAll(
|
||||
range,
|
||||
);
|
||||
} else {
|
||||
withdrawalGroupRecords =
|
||||
await tx.withdrawalGroups.indexes.byStatus.getAll();
|
||||
@ -344,12 +352,8 @@ export async function iterRecordsForRefund(
|
||||
f: (r: RefundGroupRecord) => Promise<void>,
|
||||
): Promise<void> {
|
||||
if (filter.onlyState === "nonfinal") {
|
||||
const keyRange = GlobalIDB.KeyRange.only(
|
||||
RefundGroupStatus.Pending
|
||||
);
|
||||
await tx.refundGroups.indexes.byStatus
|
||||
.iter(keyRange)
|
||||
.forEachAsync(f);
|
||||
const keyRange = GlobalIDB.KeyRange.only(RefundGroupStatus.Pending);
|
||||
await tx.refundGroups.indexes.byStatus.iter(keyRange).forEachAsync(f);
|
||||
} else {
|
||||
await tx.refundGroups.iter().forEachAsync(f);
|
||||
}
|
||||
|
@ -1190,14 +1190,14 @@ export async function autoRefresh(
|
||||
`created refresh group for auto-refresh (${res.refreshGroupId})`,
|
||||
);
|
||||
}
|
||||
// logger.trace(
|
||||
// `current wallet time: ${AbsoluteTime.toIsoString(AbsoluteTime.now())}`,
|
||||
// );
|
||||
// logger.trace(
|
||||
// `current wallet time: ${AbsoluteTime.toIsoString(AbsoluteTime.now())}`,
|
||||
// );
|
||||
logger.trace(
|
||||
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
|
||||
);
|
||||
exchange.nextRefreshCheck =
|
||||
AbsoluteTime.toPreciseTimestamp(minCheckThreshold);
|
||||
exchange.nextRefreshCheckStampMs =
|
||||
AbsoluteTime.toStampMs(minCheckThreshold);
|
||||
await tx.exchanges.put(exchange);
|
||||
});
|
||||
return TaskRunResult.finished();
|
||||
|
@ -128,6 +128,8 @@ import {
|
||||
} from "../util/coinSelection.js";
|
||||
import {
|
||||
ExchangeDetailsRecord,
|
||||
ExchangeEntryDbRecordStatus,
|
||||
ExchangeEntryDbUpdateStatus,
|
||||
PendingTaskType,
|
||||
isWithdrawableDenom,
|
||||
} from "../index.js";
|
||||
@ -2341,10 +2343,6 @@ export async function internalPerformCreateWithdrawalGroup(
|
||||
}>,
|
||||
prep: PrepareCreateWithdrawalGroupResult,
|
||||
): Promise<PerformCreateWithdrawalGroupResult> {
|
||||
const transactionId = constructTransactionIdentifier({
|
||||
tag: TransactionType.Withdrawal,
|
||||
withdrawalGroupId: prep.withdrawalGroup.withdrawalGroupId,
|
||||
});
|
||||
const { withdrawalGroup } = prep;
|
||||
if (!prep.creationInfo) {
|
||||
return { withdrawalGroup, transitionInfo: undefined };
|
||||
@ -2361,6 +2359,7 @@ export async function internalPerformCreateWithdrawalGroup(
|
||||
const exchange = await tx.exchanges.get(withdrawalGroup.exchangeBaseUrl);
|
||||
if (exchange) {
|
||||
exchange.lastWithdrawal = TalerPreciseTimestamp.now();
|
||||
exchange.entryStatus = ExchangeEntryDbRecordStatus.Used;
|
||||
await tx.exchanges.put(exchange);
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,7 @@ import {
|
||||
} from "./operations/deposits.js";
|
||||
import {
|
||||
acceptExchangeTermsOfService,
|
||||
addPresetExchangeEntry,
|
||||
downloadTosFromAcceptedFormat,
|
||||
getExchangeDetails,
|
||||
getExchangeRequestTimeout,
|
||||
@ -533,6 +534,7 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
||||
await tx.auditorTrust.put(c);
|
||||
}
|
||||
for (const baseUrl of ws.config.builtin.exchanges) {
|
||||
await addPresetExchangeEntry(tx, baseUrl);
|
||||
const now = AbsoluteTime.now();
|
||||
provideExchangeRecordInTx(ws, tx, baseUrl, now);
|
||||
}
|
||||
@ -1688,8 +1690,7 @@ export class Wallet {
|
||||
|
||||
public static defaultConfig: Readonly<WalletConfig> = {
|
||||
builtin: {
|
||||
//exchanges: ["https://exchange.demo.taler.net/"],
|
||||
exchanges: [],
|
||||
exchanges: ["https://exchange.demo.taler.net/"],
|
||||
auditors: [
|
||||
{
|
||||
currency: "KUDOS",
|
||||
|
Loading…
Reference in New Issue
Block a user