wallet-core: consistently use usec timestamps in DB
This commit is contained in:
parent
f4587c44fd
commit
1ce53e1c21
@ -67,7 +67,7 @@ export interface TransactionsRequest {
|
|||||||
*/
|
*/
|
||||||
includeRefreshes?: boolean;
|
includeRefreshes?: boolean;
|
||||||
|
|
||||||
filterByState?: TransactionStateFilter
|
filterByState?: TransactionStateFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionState {
|
export interface TransactionState {
|
||||||
@ -629,6 +629,17 @@ export interface TransactionRefresh extends TransactionCommon {
|
|||||||
refreshOutputAmount: AmountString;
|
refreshOutputAmount: AmountString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DepositTransactionTrackingState {
|
||||||
|
// Raw wire transfer identifier of the deposit.
|
||||||
|
wireTransferId: string;
|
||||||
|
// When was the wire transfer given to the bank.
|
||||||
|
timestampExecuted: TalerProtocolTimestamp;
|
||||||
|
// Total amount transfer for this wtid (including fees)
|
||||||
|
amountRaw: AmountString;
|
||||||
|
// Wire fee amount for this exchange
|
||||||
|
wireFee: AmountString;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deposit transaction, which effectively sends
|
* Deposit transaction, which effectively sends
|
||||||
* money from this wallet somewhere else.
|
* money from this wallet somewhere else.
|
||||||
@ -662,16 +673,7 @@ export interface TransactionDeposit extends TransactionCommon {
|
|||||||
*/
|
*/
|
||||||
deposited: boolean;
|
deposited: boolean;
|
||||||
|
|
||||||
trackingState: Array<{
|
trackingState: Array<DepositTransactionTrackingState>;
|
||||||
// Raw wire transfer identifier of the deposit.
|
|
||||||
wireTransferId: string;
|
|
||||||
// When was the wire transfer given to the bank.
|
|
||||||
timestampExecuted: TalerProtocolTimestamp;
|
|
||||||
// Total amount transfer for this wtid (including fees)
|
|
||||||
amountRaw: AmountString;
|
|
||||||
// Wire fee amount for this exchange
|
|
||||||
wireFee: AmountString;
|
|
||||||
}>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionByIdRequest {
|
export interface TransactionByIdRequest {
|
||||||
|
@ -87,7 +87,7 @@ import {
|
|||||||
WithdrawalPlanchet,
|
WithdrawalPlanchet,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
// FIXME: Crypto should not use DB Types!
|
// FIXME: Crypto should not use DB Types!
|
||||||
import { DenominationRecord } from "../db.js";
|
import { DenominationRecord, timestampProtocolFromDb } from "../db.js";
|
||||||
import {
|
import {
|
||||||
CreateRecoupRefreshReqRequest,
|
CreateRecoupRefreshReqRequest,
|
||||||
CreateRecoupReqRequest,
|
CreateRecoupReqRequest,
|
||||||
@ -962,10 +962,22 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
|
|||||||
const value: AmountJson = Amounts.parseOrThrow(denom.value);
|
const value: AmountJson = Amounts.parseOrThrow(denom.value);
|
||||||
const p = buildSigPS(TalerSignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY)
|
const p = buildSigPS(TalerSignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY)
|
||||||
.put(decodeCrock(masterPub))
|
.put(decodeCrock(masterPub))
|
||||||
.put(timestampRoundedToBuffer(denom.stampStart))
|
.put(timestampRoundedToBuffer(timestampProtocolFromDb(denom.stampStart)))
|
||||||
.put(timestampRoundedToBuffer(denom.stampExpireWithdraw))
|
.put(
|
||||||
.put(timestampRoundedToBuffer(denom.stampExpireDeposit))
|
timestampRoundedToBuffer(
|
||||||
.put(timestampRoundedToBuffer(denom.stampExpireLegal))
|
timestampProtocolFromDb(denom.stampExpireWithdraw),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.put(
|
||||||
|
timestampRoundedToBuffer(
|
||||||
|
timestampProtocolFromDb(denom.stampExpireDeposit),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.put(
|
||||||
|
timestampRoundedToBuffer(
|
||||||
|
timestampProtocolFromDb(denom.stampExpireLegal),
|
||||||
|
),
|
||||||
|
)
|
||||||
.put(amountToBuffer(value))
|
.put(amountToBuffer(value))
|
||||||
.put(amountToBuffer(denom.fees.feeWithdraw))
|
.put(amountToBuffer(denom.fees.feeWithdraw))
|
||||||
.put(amountToBuffer(denom.fees.feeDeposit))
|
.put(amountToBuffer(denom.fees.feeDeposit))
|
||||||
|
@ -27,6 +27,7 @@ import {
|
|||||||
structuredEncapsulate,
|
structuredEncapsulate,
|
||||||
} from "@gnu-taler/idb-bridge";
|
} from "@gnu-taler/idb-bridge";
|
||||||
import {
|
import {
|
||||||
|
AbsoluteTime,
|
||||||
AgeCommitmentProof,
|
AgeCommitmentProof,
|
||||||
AmountString,
|
AmountString,
|
||||||
Amounts,
|
Amounts,
|
||||||
@ -51,12 +52,13 @@ import {
|
|||||||
TalerPreciseTimestamp,
|
TalerPreciseTimestamp,
|
||||||
TalerProtocolDuration,
|
TalerProtocolDuration,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
|
//TalerProtocolTimestamp,
|
||||||
TransactionIdStr,
|
TransactionIdStr,
|
||||||
UnblindedSignature,
|
UnblindedSignature,
|
||||||
WireInfo,
|
WireInfo,
|
||||||
codecForAny,
|
codecForAny,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { RetryInfo, TaskIdentifiers } from "./operations/common.js";
|
import { DbRetryInfo, TaskIdentifiers } from "./operations/common.js";
|
||||||
import {
|
import {
|
||||||
DbAccess,
|
DbAccess,
|
||||||
DbReadOnlyTransaction,
|
DbReadOnlyTransaction,
|
||||||
@ -193,6 +195,44 @@ export function timestampPreciseToDb(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function timestampProtocolToDb(
|
||||||
|
stamp: TalerProtocolTimestamp,
|
||||||
|
): DbProtocolTimestamp {
|
||||||
|
if (stamp.t_s === "never") {
|
||||||
|
return DB_TIMESTAMP_FOREVER as DbProtocolTimestamp;
|
||||||
|
} else {
|
||||||
|
let tUs = stamp.t_s * 1000000;
|
||||||
|
return tUs as DbProtocolTimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timestampProtocolFromDb(
|
||||||
|
stamp: DbProtocolTimestamp,
|
||||||
|
): TalerProtocolTimestamp {
|
||||||
|
return TalerProtocolTimestamp.fromSeconds(Math.floor(stamp / 1000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timestampAbsoluteFromDb(
|
||||||
|
stamp: DbProtocolTimestamp | DbPreciseTimestamp,
|
||||||
|
): AbsoluteTime {
|
||||||
|
if (stamp >= DB_TIMESTAMP_FOREVER) {
|
||||||
|
return AbsoluteTime.never();
|
||||||
|
}
|
||||||
|
return AbsoluteTime.fromMilliseconds(Math.floor(stamp / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timestampOptionalAbsoluteFromDb(
|
||||||
|
stamp: DbProtocolTimestamp | DbPreciseTimestamp | undefined,
|
||||||
|
): AbsoluteTime | undefined {
|
||||||
|
if (stamp == null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (stamp >= DB_TIMESTAMP_FOREVER) {
|
||||||
|
return AbsoluteTime.never();
|
||||||
|
}
|
||||||
|
return AbsoluteTime.fromMilliseconds(Math.floor(stamp / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format of the operation status code: 0x0abc_nnnn
|
* Format of the operation status code: 0x0abc_nnnn
|
||||||
|
|
||||||
@ -391,22 +431,22 @@ export interface DenominationRecord {
|
|||||||
/**
|
/**
|
||||||
* Validity start date of the denomination.
|
* Validity start date of the denomination.
|
||||||
*/
|
*/
|
||||||
stampStart: TalerProtocolTimestamp;
|
stampStart: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date after which the currency can't be withdrawn anymore.
|
* Date after which the currency can't be withdrawn anymore.
|
||||||
*/
|
*/
|
||||||
stampExpireWithdraw: TalerProtocolTimestamp;
|
stampExpireWithdraw: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date after the denomination officially doesn't exist anymore.
|
* Date after the denomination officially doesn't exist anymore.
|
||||||
*/
|
*/
|
||||||
stampExpireLegal: TalerProtocolTimestamp;
|
stampExpireLegal: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data after which coins of this denomination can't be deposited anymore.
|
* Data after which coins of this denomination can't be deposited anymore.
|
||||||
*/
|
*/
|
||||||
stampExpireDeposit: TalerProtocolTimestamp;
|
stampExpireDeposit: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature by the exchange's master key over the denomination
|
* Signature by the exchange's master key over the denomination
|
||||||
@ -448,7 +488,7 @@ export interface DenominationRecord {
|
|||||||
* Latest list issue date of the "/keys" response
|
* Latest list issue date of the "/keys" response
|
||||||
* that includes this denomination.
|
* that includes this denomination.
|
||||||
*/
|
*/
|
||||||
listIssueDate: TalerProtocolTimestamp;
|
listIssueDate: DbProtocolTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace DenominationRecord {
|
export namespace DenominationRecord {
|
||||||
@ -460,10 +500,10 @@ export namespace DenominationRecord {
|
|||||||
feeRefresh: Amounts.stringify(d.fees.feeRefresh),
|
feeRefresh: Amounts.stringify(d.fees.feeRefresh),
|
||||||
feeRefund: Amounts.stringify(d.fees.feeRefund),
|
feeRefund: Amounts.stringify(d.fees.feeRefund),
|
||||||
feeWithdraw: Amounts.stringify(d.fees.feeWithdraw),
|
feeWithdraw: Amounts.stringify(d.fees.feeWithdraw),
|
||||||
stampExpireDeposit: d.stampExpireDeposit,
|
stampExpireDeposit: timestampProtocolFromDb(d.stampExpireDeposit),
|
||||||
stampExpireLegal: d.stampExpireLegal,
|
stampExpireLegal: timestampProtocolFromDb(d.stampExpireLegal),
|
||||||
stampExpireWithdraw: d.stampExpireWithdraw,
|
stampExpireWithdraw: timestampProtocolFromDb(d.stampExpireWithdraw),
|
||||||
stampStart: d.stampStart,
|
stampStart: timestampProtocolFromDb(d.stampStart),
|
||||||
value: Amounts.stringify(d.value),
|
value: Amounts.stringify(d.value),
|
||||||
exchangeBaseUrl: d.exchangeBaseUrl,
|
exchangeBaseUrl: d.exchangeBaseUrl,
|
||||||
};
|
};
|
||||||
@ -471,9 +511,9 @@ export namespace DenominationRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ExchangeSignkeysRecord {
|
export interface ExchangeSignkeysRecord {
|
||||||
stampStart: TalerProtocolTimestamp;
|
stampStart: DbProtocolTimestamp;
|
||||||
stampExpire: TalerProtocolTimestamp;
|
stampExpire: DbProtocolTimestamp;
|
||||||
stampEnd: TalerProtocolTimestamp;
|
stampEnd: DbProtocolTimestamp;
|
||||||
signkeyPub: EddsaPublicKeyString;
|
signkeyPub: EddsaPublicKeyString;
|
||||||
masterSig: EddsaSignatureString;
|
masterSig: EddsaSignatureString;
|
||||||
|
|
||||||
@ -590,11 +630,6 @@ export enum ExchangeEntryDbUpdateStatus {
|
|||||||
ReadyUpdate = 7,
|
ReadyUpdate = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamp stored as a IEEE 754 double, in milliseconds.
|
|
||||||
*/
|
|
||||||
export type DbIndexableTimestampMs = number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchange record as stored in the wallet's database.
|
* Exchange record as stored in the wallet's database.
|
||||||
*/
|
*/
|
||||||
@ -634,13 +669,8 @@ export interface ExchangeEntryRecord {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Next scheduled update for the exchange.
|
* Next scheduled update for the exchange.
|
||||||
*
|
|
||||||
* (This field must always be present, so we can index on the timestamp.)
|
|
||||||
*
|
|
||||||
* FIXME: To index on the timestamp, this needs to be a number of
|
|
||||||
* binary timestamp!
|
|
||||||
*/
|
*/
|
||||||
nextUpdateStampMs: DbIndexableTimestampMs;
|
nextUpdateStamp: DbPreciseTimestamp;
|
||||||
|
|
||||||
lastKeysEtag: string | undefined;
|
lastKeysEtag: string | undefined;
|
||||||
|
|
||||||
@ -650,7 +680,7 @@ export interface ExchangeEntryRecord {
|
|||||||
* Updated whenever the exchange's denominations are updated or when
|
* Updated whenever the exchange's denominations are updated or when
|
||||||
* the refresh check has been done.
|
* the refresh check has been done.
|
||||||
*/
|
*/
|
||||||
nextRefreshCheckStampMs: DbIndexableTimestampMs;
|
nextRefreshCheckStamp: DbPreciseTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public key of the reserve that we're currently using for
|
* Public key of the reserve that we're currently using for
|
||||||
@ -873,7 +903,7 @@ export interface RewardRecord {
|
|||||||
/**
|
/**
|
||||||
* Timestamp, the tip can't be picked up anymore after this deadline.
|
* Timestamp, the tip can't be picked up anymore after this deadline.
|
||||||
*/
|
*/
|
||||||
rewardExpiration: TalerProtocolTimestamp;
|
rewardExpiration: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The exchange that will sign our coins, chosen by the merchant.
|
* The exchange that will sign our coins, chosen by the merchant.
|
||||||
@ -1287,7 +1317,7 @@ export interface PurchaseRecord {
|
|||||||
/**
|
/**
|
||||||
* Continue querying the refund status until this deadline has expired.
|
* Continue querying the refund status until this deadline has expired.
|
||||||
*/
|
*/
|
||||||
autoRefundDeadline: TalerProtocolTimestamp | undefined;
|
autoRefundDeadline: DbProtocolTimestamp | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much merchant has refund to be taken but the wallet
|
* How much merchant has refund to be taken but the wallet
|
||||||
@ -1668,7 +1698,7 @@ export interface DepositTrackingInfo {
|
|||||||
// Raw wire transfer identifier of the deposit.
|
// Raw wire transfer identifier of the deposit.
|
||||||
wireTransferId: string;
|
wireTransferId: string;
|
||||||
// When was the wire transfer given to the bank.
|
// When was the wire transfer given to the bank.
|
||||||
timestampExecuted: TalerProtocolTimestamp;
|
timestampExecuted: DbProtocolTimestamp;
|
||||||
// Total amount transfer for this wtid (including fees)
|
// Total amount transfer for this wtid (including fees)
|
||||||
amountRaw: AmountString;
|
amountRaw: AmountString;
|
||||||
// Wire fee amount for this exchange
|
// Wire fee amount for this exchange
|
||||||
@ -1690,7 +1720,7 @@ export interface DepositGroupRecord {
|
|||||||
*/
|
*/
|
||||||
amount: AmountString;
|
amount: AmountString;
|
||||||
|
|
||||||
wireTransferDeadline: TalerProtocolTimestamp;
|
wireTransferDeadline: DbProtocolTimestamp;
|
||||||
|
|
||||||
merchantPub: string;
|
merchantPub: string;
|
||||||
merchantPriv: string;
|
merchantPriv: string;
|
||||||
@ -1831,7 +1861,7 @@ export interface PeerPushDebitRecord {
|
|||||||
*/
|
*/
|
||||||
contractEncNonce: string;
|
contractEncNonce: string;
|
||||||
|
|
||||||
purseExpiration: TalerProtocolTimestamp;
|
purseExpiration: DbProtocolTimestamp;
|
||||||
|
|
||||||
timestampCreated: DbPreciseTimestamp;
|
timestampCreated: DbPreciseTimestamp;
|
||||||
|
|
||||||
@ -2077,7 +2107,7 @@ export interface OperationRetryRecord {
|
|||||||
|
|
||||||
lastError?: TalerErrorDetail;
|
lastError?: TalerErrorDetail;
|
||||||
|
|
||||||
retryInfo: RetryInfo;
|
retryInfo: DbRetryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2130,9 +2160,8 @@ export interface UserAttentionRecord {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* When the notification was created.
|
* When the notification was created.
|
||||||
* FIXME: This should be a TalerPreciseTimestamp
|
|
||||||
*/
|
*/
|
||||||
createdMs: number;
|
created: DbPreciseTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the user mark this notification as read.
|
* When the user mark this notification as read.
|
||||||
@ -2233,7 +2262,7 @@ export interface RefundItemRecord {
|
|||||||
/**
|
/**
|
||||||
* Execution time as claimed by the merchant
|
* Execution time as claimed by the merchant
|
||||||
*/
|
*/
|
||||||
executionTime: TalerProtocolTimestamp;
|
executionTime: DbProtocolTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time when the wallet became aware of the refund.
|
* Time when the wallet became aware of the refund.
|
||||||
|
@ -31,7 +31,7 @@ import {
|
|||||||
UserAttentionUnreadList,
|
UserAttentionUnreadList,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { timestampPreciseToDb } from "../index.js";
|
import { timestampPreciseFromDb, timestampPreciseToDb } from "../index.js";
|
||||||
|
|
||||||
const logger = new Logger("operations/attention.ts");
|
const logger = new Logger("operations/attention.ts");
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ export async function getUserAttentions(
|
|||||||
return;
|
return;
|
||||||
pending.push({
|
pending.push({
|
||||||
info: x.info,
|
info: x.info,
|
||||||
when: TalerPreciseTimestamp.fromMilliseconds(x.createdMs),
|
when: timestampPreciseFromDb(x.created),
|
||||||
read: x.read !== undefined,
|
read: x.read !== undefined,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -118,7 +118,7 @@ export async function addAttentionRequest(
|
|||||||
await tx.userAttention.put({
|
await tx.userAttention.put({
|
||||||
info,
|
info,
|
||||||
entityId,
|
entityId,
|
||||||
createdMs: AbsoluteTime.now().t_ms as number,
|
created: timestampPreciseToDb(TalerPreciseTimestamp.now()),
|
||||||
read: undefined,
|
read: undefined,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,6 +40,7 @@ import {
|
|||||||
TalerError,
|
TalerError,
|
||||||
TalerErrorCode,
|
TalerErrorCode,
|
||||||
TalerErrorDetail,
|
TalerErrorDetail,
|
||||||
|
TalerPreciseTimestamp,
|
||||||
TombstoneIdStr,
|
TombstoneIdStr,
|
||||||
TransactionIdStr,
|
TransactionIdStr,
|
||||||
TransactionType,
|
TransactionType,
|
||||||
@ -49,6 +50,7 @@ import { CryptoApiStoppedError } from "../crypto/workers/crypto-dispatcher.js";
|
|||||||
import {
|
import {
|
||||||
BackupProviderRecord,
|
BackupProviderRecord,
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
|
DbPreciseTimestamp,
|
||||||
DepositGroupRecord,
|
DepositGroupRecord,
|
||||||
ExchangeDetailsRecord,
|
ExchangeDetailsRecord,
|
||||||
ExchangeEntryDbRecordStatus,
|
ExchangeEntryDbRecordStatus,
|
||||||
@ -62,6 +64,7 @@ import {
|
|||||||
RecoupGroupRecord,
|
RecoupGroupRecord,
|
||||||
RefreshGroupRecord,
|
RefreshGroupRecord,
|
||||||
RewardRecord,
|
RewardRecord,
|
||||||
|
timestampPreciseToDb,
|
||||||
WalletStoresV1,
|
WalletStoresV1,
|
||||||
WithdrawalGroupRecord,
|
WithdrawalGroupRecord,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
@ -360,11 +363,11 @@ async function storePendingTaskError(
|
|||||||
retryRecord = {
|
retryRecord = {
|
||||||
id: pendingTaskId,
|
id: pendingTaskId,
|
||||||
lastError: e,
|
lastError: e,
|
||||||
retryInfo: RetryInfo.reset(),
|
retryInfo: DbRetryInfo.reset(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
retryRecord.lastError = e;
|
retryRecord.lastError = e;
|
||||||
retryRecord.retryInfo = RetryInfo.increment(retryRecord.retryInfo);
|
retryRecord.retryInfo = DbRetryInfo.increment(retryRecord.retryInfo);
|
||||||
}
|
}
|
||||||
await tx.operationRetries.put(retryRecord);
|
await tx.operationRetries.put(retryRecord);
|
||||||
return taskToTransactionNotification(ws, tx, pendingTaskId, e);
|
return taskToTransactionNotification(ws, tx, pendingTaskId, e);
|
||||||
@ -383,7 +386,7 @@ export async function resetPendingTaskTimeout(
|
|||||||
if (retryRecord) {
|
if (retryRecord) {
|
||||||
// Note that we don't reset the lastError, it should still be visible
|
// Note that we don't reset the lastError, it should still be visible
|
||||||
// while the retry runs.
|
// while the retry runs.
|
||||||
retryRecord.retryInfo = RetryInfo.reset();
|
retryRecord.retryInfo = DbRetryInfo.reset();
|
||||||
await tx.operationRetries.put(retryRecord);
|
await tx.operationRetries.put(retryRecord);
|
||||||
}
|
}
|
||||||
return taskToTransactionNotification(ws, tx, pendingTaskId, undefined);
|
return taskToTransactionNotification(ws, tx, pendingTaskId, undefined);
|
||||||
@ -403,14 +406,14 @@ async function storePendingTaskPending(
|
|||||||
if (!retryRecord) {
|
if (!retryRecord) {
|
||||||
retryRecord = {
|
retryRecord = {
|
||||||
id: pendingTaskId,
|
id: pendingTaskId,
|
||||||
retryInfo: RetryInfo.reset(),
|
retryInfo: DbRetryInfo.reset(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (retryRecord.lastError) {
|
if (retryRecord.lastError) {
|
||||||
hadError = true;
|
hadError = true;
|
||||||
}
|
}
|
||||||
delete retryRecord.lastError;
|
delete retryRecord.lastError;
|
||||||
retryRecord.retryInfo = RetryInfo.increment(retryRecord.retryInfo);
|
retryRecord.retryInfo = DbRetryInfo.increment(retryRecord.retryInfo);
|
||||||
}
|
}
|
||||||
await tx.operationRetries.put(retryRecord);
|
await tx.operationRetries.put(retryRecord);
|
||||||
if (hadError) {
|
if (hadError) {
|
||||||
@ -736,9 +739,9 @@ export interface TaskRunLongpollResult {
|
|||||||
type: TaskRunResultType.Longpoll;
|
type: TaskRunResultType.Longpoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RetryInfo {
|
export interface DbRetryInfo {
|
||||||
firstTry: AbsoluteTime;
|
firstTry: DbPreciseTimestamp;
|
||||||
nextRetry: AbsoluteTime;
|
nextRetry: DbPreciseTimestamp;
|
||||||
retryCounter: number;
|
retryCounter: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,7 +758,7 @@ const defaultRetryPolicy: RetryPolicy = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function updateTimeout(
|
function updateTimeout(
|
||||||
r: RetryInfo,
|
r: DbRetryInfo,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
): void {
|
): void {
|
||||||
const now = AbsoluteTime.now();
|
const now = AbsoluteTime.now();
|
||||||
@ -763,7 +766,9 @@ function updateTimeout(
|
|||||||
throw Error("assertion failed");
|
throw Error("assertion failed");
|
||||||
}
|
}
|
||||||
if (p.backoffDelta.d_ms === "forever") {
|
if (p.backoffDelta.d_ms === "forever") {
|
||||||
r.nextRetry = AbsoluteTime.never();
|
r.nextRetry = timestampPreciseToDb(
|
||||||
|
AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,12 +780,12 @@ function updateTimeout(
|
|||||||
(p.maxTimeout.d_ms === "forever"
|
(p.maxTimeout.d_ms === "forever"
|
||||||
? nextIncrement
|
? nextIncrement
|
||||||
: Math.min(p.maxTimeout.d_ms, nextIncrement));
|
: Math.min(p.maxTimeout.d_ms, nextIncrement));
|
||||||
r.nextRetry = AbsoluteTime.fromMilliseconds(t);
|
r.nextRetry = timestampPreciseToDb(TalerPreciseTimestamp.fromMilliseconds(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace RetryInfo {
|
export namespace DbRetryInfo {
|
||||||
export function getDuration(
|
export function getDuration(
|
||||||
r: RetryInfo | undefined,
|
r: DbRetryInfo | undefined,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
): Duration {
|
): Duration {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@ -797,11 +802,11 @@ export namespace RetryInfo {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reset(p: RetryPolicy = defaultRetryPolicy): RetryInfo {
|
export function reset(p: RetryPolicy = defaultRetryPolicy): DbRetryInfo {
|
||||||
const now = AbsoluteTime.now();
|
const now = TalerPreciseTimestamp.now();
|
||||||
const info = {
|
const info: DbRetryInfo = {
|
||||||
firstTry: now,
|
firstTry: timestampPreciseToDb(now),
|
||||||
nextRetry: now,
|
nextRetry: timestampPreciseToDb(now),
|
||||||
retryCounter: 0,
|
retryCounter: 0,
|
||||||
};
|
};
|
||||||
updateTimeout(info, p);
|
updateTimeout(info, p);
|
||||||
@ -809,9 +814,9 @@ export namespace RetryInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function increment(
|
export function increment(
|
||||||
r: RetryInfo | undefined,
|
r: DbRetryInfo | undefined,
|
||||||
p: RetryPolicy = defaultRetryPolicy,
|
p: RetryPolicy = defaultRetryPolicy,
|
||||||
): RetryInfo {
|
): DbRetryInfo {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return reset(p);
|
return reset(p);
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,8 @@ import {
|
|||||||
createRefreshGroup,
|
createRefreshGroup,
|
||||||
getTotalRefreshCost,
|
getTotalRefreshCost,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
|
timestampProtocolToDb,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { assertUnreachable } from "../util/assertUnreachable.js";
|
import { assertUnreachable } from "../util/assertUnreachable.js";
|
||||||
@ -800,7 +802,7 @@ async function processDepositGroupPendingTrack(
|
|||||||
amountRaw: Amounts.stringify(raw),
|
amountRaw: Amounts.stringify(raw),
|
||||||
wireFee: Amounts.stringify(wireFee),
|
wireFee: Amounts.stringify(wireFee),
|
||||||
exchangePub: track.exchange_pub,
|
exchangePub: track.exchange_pub,
|
||||||
timestampExecuted: track.execution_time,
|
timestampExecuted: timestampProtocolToDb(track.execution_time),
|
||||||
wireTransferId: track.wtid,
|
wireTransferId: track.wtid,
|
||||||
},
|
},
|
||||||
id: track.exchange_sig,
|
id: track.exchange_sig,
|
||||||
@ -1393,7 +1395,9 @@ export async function createDepositGroup(
|
|||||||
counterpartyEffectiveDepositAmount: Amounts.stringify(
|
counterpartyEffectiveDepositAmount: Amounts.stringify(
|
||||||
counterpartyEffectiveDepositAmount,
|
counterpartyEffectiveDepositAmount,
|
||||||
),
|
),
|
||||||
wireTransferDeadline: contractTerms.wire_transfer_deadline,
|
wireTransferDeadline: timestampProtocolToDb(
|
||||||
|
contractTerms.wire_transfer_deadline,
|
||||||
|
),
|
||||||
wire: {
|
wire: {
|
||||||
payto_uri: req.depositPaytoUri,
|
payto_uri: req.depositPaytoUri,
|
||||||
salt: wireSalt,
|
salt: wireSalt,
|
||||||
|
@ -74,7 +74,9 @@ import {
|
|||||||
ExchangeEntryDbRecordStatus,
|
ExchangeEntryDbRecordStatus,
|
||||||
ExchangeEntryDbUpdateStatus,
|
ExchangeEntryDbUpdateStatus,
|
||||||
isWithdrawableDenom,
|
isWithdrawableDenom,
|
||||||
|
timestampPreciseFromDb,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolToDb,
|
||||||
WalletDbReadWriteTransaction,
|
WalletDbReadWriteTransaction,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
|
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
|
||||||
@ -317,8 +319,12 @@ export async function addPresetExchangeEntry(
|
|||||||
detailsPointer: undefined,
|
detailsPointer: undefined,
|
||||||
lastUpdate: undefined,
|
lastUpdate: undefined,
|
||||||
lastKeysEtag: undefined,
|
lastKeysEtag: undefined,
|
||||||
nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
|
nextRefreshCheckStamp: timestampPreciseToDb(
|
||||||
nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
|
AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
|
||||||
|
),
|
||||||
|
nextUpdateStamp: timestampPreciseToDb(
|
||||||
|
AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
await tx.exchanges.put(r);
|
await tx.exchanges.put(r);
|
||||||
}
|
}
|
||||||
@ -344,8 +350,12 @@ export async function provideExchangeRecordInTx(
|
|||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
detailsPointer: undefined,
|
detailsPointer: undefined,
|
||||||
lastUpdate: undefined,
|
lastUpdate: undefined,
|
||||||
nextUpdateStampMs: AbsoluteTime.getStampMsNever(),
|
nextUpdateStamp: timestampPreciseToDb(
|
||||||
nextRefreshCheckStampMs: AbsoluteTime.getStampMsNever(),
|
AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
|
||||||
|
),
|
||||||
|
nextRefreshCheckStamp: timestampPreciseToDb(
|
||||||
|
AbsoluteTime.toPreciseTimestamp(AbsoluteTime.never()),
|
||||||
|
),
|
||||||
lastKeysEtag: undefined,
|
lastKeysEtag: undefined,
|
||||||
};
|
};
|
||||||
await tx.exchanges.put(r);
|
await tx.exchanges.put(r);
|
||||||
@ -446,13 +456,19 @@ async function downloadExchangeKeysInfo(
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
value: Amounts.stringify(value),
|
value: Amounts.stringify(value),
|
||||||
currency: value.currency,
|
currency: value.currency,
|
||||||
stampExpireDeposit: denomIn.stamp_expire_deposit,
|
stampExpireDeposit: timestampProtocolToDb(
|
||||||
stampExpireLegal: denomIn.stamp_expire_legal,
|
denomIn.stamp_expire_deposit,
|
||||||
stampExpireWithdraw: denomIn.stamp_expire_withdraw,
|
),
|
||||||
stampStart: denomIn.stamp_start,
|
stampExpireLegal: timestampProtocolToDb(denomIn.stamp_expire_legal),
|
||||||
|
stampExpireWithdraw: timestampProtocolToDb(
|
||||||
|
denomIn.stamp_expire_withdraw,
|
||||||
|
),
|
||||||
|
stampStart: timestampProtocolToDb(denomIn.stamp_start),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
masterSig: denomIn.master_sig,
|
masterSig: denomIn.master_sig,
|
||||||
listIssueDate: exchangeKeysJsonUnchecked.list_issue_date,
|
listIssueDate: timestampProtocolToDb(
|
||||||
|
exchangeKeysJsonUnchecked.list_issue_date,
|
||||||
|
),
|
||||||
fees: {
|
fees: {
|
||||||
feeDeposit: Amounts.stringify(denomGroup.fee_deposit),
|
feeDeposit: Amounts.stringify(denomGroup.fee_deposit),
|
||||||
feeRefresh: Amounts.stringify(denomGroup.fee_refresh),
|
feeRefresh: Amounts.stringify(denomGroup.fee_refresh),
|
||||||
@ -614,7 +630,9 @@ export async function updateExchangeFromUrlHandler(
|
|||||||
!forceNow &&
|
!forceNow &&
|
||||||
exchangeDetails !== undefined &&
|
exchangeDetails !== undefined &&
|
||||||
!AbsoluteTime.isExpired(
|
!AbsoluteTime.isExpired(
|
||||||
AbsoluteTime.fromStampMs(exchange.nextUpdateStampMs),
|
AbsoluteTime.fromPreciseTimestamp(
|
||||||
|
timestampPreciseFromDb(exchange.nextUpdateStamp),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
logger.trace("using existing exchange info");
|
logger.trace("using existing exchange info");
|
||||||
@ -755,11 +773,15 @@ export async function updateExchangeFromUrlHandler(
|
|||||||
newDetails.rowId = existingDetails.rowId;
|
newDetails.rowId = existingDetails.rowId;
|
||||||
}
|
}
|
||||||
r.lastUpdate = timestampPreciseToDb(TalerPreciseTimestamp.now());
|
r.lastUpdate = timestampPreciseToDb(TalerPreciseTimestamp.now());
|
||||||
r.nextUpdateStampMs = AbsoluteTime.toStampMs(
|
r.nextUpdateStamp = timestampPreciseToDb(
|
||||||
AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
|
AbsoluteTime.toPreciseTimestamp(
|
||||||
|
AbsoluteTime.fromProtocolTimestamp(keysInfo.expiry),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// New denominations might be available.
|
// New denominations might be available.
|
||||||
r.nextRefreshCheckStampMs = AbsoluteTime.getStampMsNow();
|
r.nextRefreshCheckStamp = timestampPreciseToDb(
|
||||||
|
TalerPreciseTimestamp.now(),
|
||||||
|
);
|
||||||
if (detailsPointerChanged) {
|
if (detailsPointerChanged) {
|
||||||
r.detailsPointer = {
|
r.detailsPointer = {
|
||||||
currency: newDetails.currency,
|
currency: newDetails.currency,
|
||||||
@ -777,9 +799,9 @@ export async function updateExchangeFromUrlHandler(
|
|||||||
exchangeDetailsRowId: drRowId.key,
|
exchangeDetailsRowId: drRowId.key,
|
||||||
masterSig: sk.master_sig,
|
masterSig: sk.master_sig,
|
||||||
signkeyPub: sk.key,
|
signkeyPub: sk.key,
|
||||||
stampEnd: sk.stamp_end,
|
stampEnd: timestampProtocolToDb(sk.stamp_end),
|
||||||
stampExpire: sk.stamp_expire,
|
stampExpire: timestampProtocolToDb(sk.stamp_expire),
|
||||||
stampStart: sk.stamp_start,
|
stampStart: timestampProtocolToDb(sk.stamp_start),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,7 +836,7 @@ export async function updateExchangeFromUrlHandler(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x.listIssueDate = keysInfo.listIssueDate;
|
x.listIssueDate = timestampProtocolToDb(keysInfo.listIssueDate);
|
||||||
if (!x.isOffered) {
|
if (!x.isOffered) {
|
||||||
x.isOffered = true;
|
x.isOffered = true;
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -104,6 +104,8 @@ import {
|
|||||||
RefundItemRecord,
|
RefundItemRecord,
|
||||||
RefundItemStatus,
|
RefundItemStatus,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
|
timestampProtocolToDb,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import {
|
import {
|
||||||
EXCHANGE_COINS_LOCK,
|
EXCHANGE_COINS_LOCK,
|
||||||
@ -115,7 +117,7 @@ import { checkDbInvariant } from "../util/invariants.js";
|
|||||||
import { GetReadOnlyAccess } from "../util/query.js";
|
import { GetReadOnlyAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
constructTaskIdentifier,
|
constructTaskIdentifier,
|
||||||
RetryInfo,
|
DbRetryInfo,
|
||||||
runLongpollAsync,
|
runLongpollAsync,
|
||||||
runTaskWithErrorReporting,
|
runTaskWithErrorReporting,
|
||||||
spendCoins,
|
spendCoins,
|
||||||
@ -217,11 +219,13 @@ async function failProposalPermanently(
|
|||||||
notifyTransition(ws, transactionId, transitionInfo);
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProposalRequestTimeout(retryInfo?: RetryInfo): Duration {
|
function getProposalRequestTimeout(retryInfo?: DbRetryInfo): Duration {
|
||||||
return Duration.clamp({
|
return Duration.clamp({
|
||||||
lower: Duration.fromSpec({ seconds: 1 }),
|
lower: Duration.fromSpec({ seconds: 1 }),
|
||||||
upper: Duration.fromSpec({ seconds: 60 }),
|
upper: Duration.fromSpec({ seconds: 60 }),
|
||||||
value: retryInfo ? RetryInfo.getDuration(retryInfo) : Duration.fromSpec({}),
|
value: retryInfo
|
||||||
|
? DbRetryInfo.getDuration(retryInfo)
|
||||||
|
: Duration.fromSpec({}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,8 +742,10 @@ async function storeFirstPaySuccess(
|
|||||||
const ar = Duration.fromTalerProtocolDuration(protoAr);
|
const ar = Duration.fromTalerProtocolDuration(protoAr);
|
||||||
logger.info("auto_refund present");
|
logger.info("auto_refund present");
|
||||||
purchase.purchaseStatus = PurchaseStatus.PendingQueryingAutoRefund;
|
purchase.purchaseStatus = PurchaseStatus.PendingQueryingAutoRefund;
|
||||||
purchase.autoRefundDeadline = AbsoluteTime.toProtocolTimestamp(
|
purchase.autoRefundDeadline = timestampProtocolToDb(
|
||||||
AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
|
AbsoluteTime.toProtocolTimestamp(
|
||||||
|
AbsoluteTime.addDuration(AbsoluteTime.now(), ar),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await tx.purchases.put(purchase);
|
await tx.purchases.put(purchase);
|
||||||
@ -2343,7 +2349,9 @@ async function processPurchaseAutoRefund(
|
|||||||
if (
|
if (
|
||||||
!purchase.autoRefundDeadline ||
|
!purchase.autoRefundDeadline ||
|
||||||
AbsoluteTime.isExpired(
|
AbsoluteTime.isExpired(
|
||||||
AbsoluteTime.fromProtocolTimestamp(purchase.autoRefundDeadline),
|
AbsoluteTime.fromProtocolTimestamp(
|
||||||
|
timestampProtocolFromDb(purchase.autoRefundDeadline),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const transitionInfo = await ws.db
|
const transitionInfo = await ws.db
|
||||||
@ -2804,7 +2812,7 @@ async function storeRefunds(
|
|||||||
const status: RefundItemStatus = getItemStatus(rf);
|
const status: RefundItemStatus = getItemStatus(rf);
|
||||||
const newItem: RefundItemRecord = {
|
const newItem: RefundItemRecord = {
|
||||||
coinPub: rf.coin_pub,
|
coinPub: rf.coin_pub,
|
||||||
executionTime: rf.execution_time,
|
executionTime: timestampProtocolToDb(rf.execution_time),
|
||||||
obtainedTime: timestampPreciseToDb(now),
|
obtainedTime: timestampPreciseToDb(now),
|
||||||
refundAmount: rf.refund_amount,
|
refundAmount: rf.refund_amount,
|
||||||
refundGroupId: newGroup.refundGroupId,
|
refundGroupId: newGroup.refundGroupId,
|
||||||
|
@ -56,10 +56,13 @@ import {
|
|||||||
RefreshOperationStatus,
|
RefreshOperationStatus,
|
||||||
createRefreshGroup,
|
createRefreshGroup,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
|
timestampProtocolToDb,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { PendingTaskType } from "../pending-types.js";
|
import { PendingTaskType } from "../pending-types.js";
|
||||||
import { assertUnreachable } from "../util/assertUnreachable.js";
|
import { assertUnreachable } from "../util/assertUnreachable.js";
|
||||||
|
import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";
|
||||||
import { checkLogicInvariant } from "../util/invariants.js";
|
import { checkLogicInvariant } from "../util/invariants.js";
|
||||||
import {
|
import {
|
||||||
TaskRunResult,
|
TaskRunResult,
|
||||||
@ -78,7 +81,6 @@ import {
|
|||||||
notifyTransition,
|
notifyTransition,
|
||||||
stopLongpolling,
|
stopLongpolling,
|
||||||
} from "./transactions.js";
|
} from "./transactions.js";
|
||||||
import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";
|
|
||||||
|
|
||||||
const logger = new Logger("pay-peer-push-debit.ts");
|
const logger = new Logger("pay-peer-push-debit.ts");
|
||||||
|
|
||||||
@ -208,7 +210,7 @@ async function processPeerPushDebitCreateReserve(
|
|||||||
mergePub: peerPushInitiation.mergePub,
|
mergePub: peerPushInitiation.mergePub,
|
||||||
minAge: 0,
|
minAge: 0,
|
||||||
purseAmount: peerPushInitiation.amount,
|
purseAmount: peerPushInitiation.amount,
|
||||||
purseExpiration,
|
purseExpiration: timestampProtocolFromDb(purseExpiration),
|
||||||
pursePriv: peerPushInitiation.pursePriv,
|
pursePriv: peerPushInitiation.pursePriv,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -667,7 +669,7 @@ export async function initiatePeerPushDebit(
|
|||||||
exchangeBaseUrl: sel.exchangeBaseUrl,
|
exchangeBaseUrl: sel.exchangeBaseUrl,
|
||||||
mergePriv: mergePair.priv,
|
mergePriv: mergePair.priv,
|
||||||
mergePub: mergePair.pub,
|
mergePub: mergePair.pub,
|
||||||
purseExpiration: purseExpiration,
|
purseExpiration: timestampProtocolToDb(purseExpiration),
|
||||||
pursePriv: pursePair.priv,
|
pursePriv: pursePair.priv,
|
||||||
pursePub: pursePair.pub,
|
pursePub: pursePair.pub,
|
||||||
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
|
timestampCreated: timestampPreciseToDb(TalerPreciseTimestamp.now()),
|
||||||
|
@ -21,43 +21,46 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
|
import { GlobalIDB } from "@gnu-taler/idb-bridge";
|
||||||
|
import { AbsoluteTime, TransactionRecordFilter } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
PurchaseStatus,
|
|
||||||
WalletStoresV1,
|
|
||||||
BackupProviderStateTag,
|
BackupProviderStateTag,
|
||||||
RefreshCoinStatus,
|
DepositElementStatus,
|
||||||
PeerPushDebitStatus,
|
|
||||||
PeerPullDebitRecordStatus,
|
|
||||||
PeerPushCreditStatus,
|
|
||||||
PeerPullPaymentCreditStatus,
|
|
||||||
WithdrawalGroupStatus,
|
|
||||||
RewardRecordStatus,
|
|
||||||
DepositOperationStatus,
|
|
||||||
RefreshGroupRecord,
|
|
||||||
WithdrawalGroupRecord,
|
|
||||||
DepositGroupRecord,
|
DepositGroupRecord,
|
||||||
RewardRecord,
|
DepositOperationStatus,
|
||||||
PurchaseRecord,
|
ExchangeEntryDbUpdateStatus,
|
||||||
PeerPullCreditRecord,
|
PeerPullCreditRecord,
|
||||||
|
PeerPullDebitRecordStatus,
|
||||||
|
PeerPullPaymentCreditStatus,
|
||||||
PeerPullPaymentIncomingRecord,
|
PeerPullPaymentIncomingRecord,
|
||||||
|
PeerPushCreditStatus,
|
||||||
PeerPushDebitRecord,
|
PeerPushDebitRecord,
|
||||||
|
PeerPushDebitStatus,
|
||||||
PeerPushPaymentIncomingRecord,
|
PeerPushPaymentIncomingRecord,
|
||||||
|
PurchaseRecord,
|
||||||
|
PurchaseStatus,
|
||||||
|
RefreshCoinStatus,
|
||||||
|
RefreshGroupRecord,
|
||||||
|
RefreshOperationStatus,
|
||||||
RefundGroupRecord,
|
RefundGroupRecord,
|
||||||
RefundGroupStatus,
|
RefundGroupStatus,
|
||||||
ExchangeEntryDbUpdateStatus,
|
RewardRecord,
|
||||||
RefreshOperationStatus,
|
RewardRecordStatus,
|
||||||
DepositElementStatus,
|
WalletStoresV1,
|
||||||
|
WithdrawalGroupRecord,
|
||||||
|
WithdrawalGroupStatus,
|
||||||
|
timestampAbsoluteFromDb,
|
||||||
|
timestampOptionalAbsoluteFromDb,
|
||||||
timestampPreciseFromDb,
|
timestampPreciseFromDb,
|
||||||
|
timestampPreciseToDb,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import {
|
import {
|
||||||
PendingOperationsResponse,
|
PendingOperationsResponse,
|
||||||
PendingTaskType,
|
PendingTaskType,
|
||||||
TaskId,
|
TaskId,
|
||||||
} from "../pending-types.js";
|
} from "../pending-types.js";
|
||||||
import { AbsoluteTime, TransactionRecordFilter } from "@gnu-taler/taler-util";
|
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
|
||||||
import { GetReadOnlyAccess } from "../util/query.js";
|
import { GetReadOnlyAccess } from "../util/query.js";
|
||||||
import { GlobalIDB } from "@gnu-taler/idb-bridge";
|
|
||||||
import { TaskIdentifiers } from "./common.js";
|
import { TaskIdentifiers } from "./common.js";
|
||||||
|
|
||||||
function getPendingCommon(
|
function getPendingCommon(
|
||||||
@ -100,12 +103,14 @@ async function gatherExchangePending(
|
|||||||
}
|
}
|
||||||
const opTag = TaskIdentifiers.forExchangeUpdate(exch);
|
const opTag = TaskIdentifiers.forExchangeUpdate(exch);
|
||||||
let opr = await tx.operationRetries.get(opTag);
|
let opr = await tx.operationRetries.get(opTag);
|
||||||
const timestampDue =
|
const timestampDue = opr?.retryInfo.nextRetry ?? exch.nextRefreshCheckStamp;
|
||||||
opr?.retryInfo.nextRetry ??
|
|
||||||
AbsoluteTime.fromStampMs(exch.nextUpdateStampMs);
|
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.ExchangeUpdate,
|
type: PendingTaskType.ExchangeUpdate,
|
||||||
...getPendingCommon(ws, opTag, timestampDue),
|
...getPendingCommon(
|
||||||
|
ws,
|
||||||
|
opTag,
|
||||||
|
AbsoluteTime.fromPreciseTimestamp(timestampPreciseFromDb(timestampDue)),
|
||||||
|
),
|
||||||
givesLifeness: false,
|
givesLifeness: false,
|
||||||
exchangeBaseUrl: exch.baseUrl,
|
exchangeBaseUrl: exch.baseUrl,
|
||||||
lastError: opr?.lastError,
|
lastError: opr?.lastError,
|
||||||
@ -116,8 +121,16 @@ async function gatherExchangePending(
|
|||||||
if (!opr?.lastError) {
|
if (!opr?.lastError) {
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.ExchangeCheckRefresh,
|
type: PendingTaskType.ExchangeCheckRefresh,
|
||||||
...getPendingCommon(ws, opTag, timestampDue),
|
...getPendingCommon(
|
||||||
timestampDue: AbsoluteTime.fromStampMs(exch.nextRefreshCheckStampMs),
|
ws,
|
||||||
|
opTag,
|
||||||
|
AbsoluteTime.fromPreciseTimestamp(
|
||||||
|
timestampPreciseFromDb(timestampDue),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
timestampDue: AbsoluteTime.fromPreciseTimestamp(
|
||||||
|
timestampPreciseFromDb(exch.nextRefreshCheckStamp),
|
||||||
|
),
|
||||||
givesLifeness: false,
|
givesLifeness: false,
|
||||||
exchangeBaseUrl: exch.baseUrl,
|
exchangeBaseUrl: exch.baseUrl,
|
||||||
});
|
});
|
||||||
@ -166,7 +179,9 @@ async function gatherRefreshPending(
|
|||||||
}
|
}
|
||||||
const opId = TaskIdentifiers.forRefresh(r);
|
const opId = TaskIdentifiers.forRefresh(r);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
const timestampDue =
|
||||||
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Refresh,
|
type: PendingTaskType.Refresh,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -223,8 +238,8 @@ async function gatherWithdrawalPending(
|
|||||||
opr = {
|
opr = {
|
||||||
id: opTag,
|
id: opTag,
|
||||||
retryInfo: {
|
retryInfo: {
|
||||||
firstTry: now,
|
firstTry: timestampPreciseToDb(AbsoluteTime.toPreciseTimestamp(now)),
|
||||||
nextRetry: now,
|
nextRetry: timestampPreciseToDb(AbsoluteTime.toPreciseTimestamp(now)),
|
||||||
retryCounter: 0,
|
retryCounter: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -234,7 +249,8 @@ async function gatherWithdrawalPending(
|
|||||||
...getPendingCommon(
|
...getPendingCommon(
|
||||||
ws,
|
ws,
|
||||||
opTag,
|
opTag,
|
||||||
opr.retryInfo?.nextRetry ?? AbsoluteTime.now(),
|
timestampOptionalAbsoluteFromDb(opr.retryInfo?.nextRetry) ??
|
||||||
|
AbsoluteTime.now(),
|
||||||
),
|
),
|
||||||
givesLifeness: true,
|
givesLifeness: true,
|
||||||
withdrawalGroupId: wsr.withdrawalGroupId,
|
withdrawalGroupId: wsr.withdrawalGroupId,
|
||||||
@ -286,7 +302,9 @@ async function gatherDepositPending(
|
|||||||
}
|
}
|
||||||
const opId = TaskIdentifiers.forDeposit(dg);
|
const opId = TaskIdentifiers.forDeposit(dg);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
const timestampDue =
|
||||||
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Deposit,
|
type: PendingTaskType.Deposit,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -331,13 +349,15 @@ async function gatherRewardPending(
|
|||||||
await iterRecordsForReward(tx, { onlyState: "nonfinal" }, async (tip) => {
|
await iterRecordsForReward(tx, { onlyState: "nonfinal" }, async (tip) => {
|
||||||
const opId = TaskIdentifiers.forTipPickup(tip);
|
const opId = TaskIdentifiers.forTipPickup(tip);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
const timestampDue =
|
||||||
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
if (tip.acceptedTimestamp) {
|
if (tip.acceptedTimestamp) {
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.RewardPickup,
|
type: PendingTaskType.RewardPickup,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
givesLifeness: true,
|
givesLifeness: true,
|
||||||
timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
|
timestampDue,
|
||||||
merchantBaseUrl: tip.merchantBaseUrl,
|
merchantBaseUrl: tip.merchantBaseUrl,
|
||||||
tipId: tip.walletRewardId,
|
tipId: tip.walletRewardId,
|
||||||
merchantTipId: tip.merchantRewardId,
|
merchantTipId: tip.merchantRewardId,
|
||||||
@ -391,7 +411,9 @@ async function gatherPurchasePending(
|
|||||||
await iterRecordsForPurchase(tx, { onlyState: "nonfinal" }, async (pr) => {
|
await iterRecordsForPurchase(tx, { onlyState: "nonfinal" }, async (pr) => {
|
||||||
const opId = TaskIdentifiers.forPay(pr);
|
const opId = TaskIdentifiers.forPay(pr);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
const timestampDue =
|
||||||
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Purchase,
|
type: PendingTaskType.Purchase,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -420,7 +442,9 @@ async function gatherRecoupPending(
|
|||||||
}
|
}
|
||||||
const opId = TaskIdentifiers.forRecoup(rg);
|
const opId = TaskIdentifiers.forRecoup(rg);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
const timestampDue =
|
||||||
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Recoup,
|
type: PendingTaskType.Recoup,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -445,8 +469,8 @@ async function gatherBackupPending(
|
|||||||
const opId = TaskIdentifiers.forBackup(bp);
|
const opId = TaskIdentifiers.forBackup(bp);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
if (bp.state.tag === BackupProviderStateTag.Ready) {
|
if (bp.state.tag === BackupProviderStateTag.Ready) {
|
||||||
const timestampDue = AbsoluteTime.fromPreciseTimestamp(
|
const timestampDue = timestampAbsoluteFromDb(
|
||||||
timestampPreciseFromDb(bp.state.nextBackupTimestamp),
|
bp.state.nextBackupTimestamp,
|
||||||
);
|
);
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Backup,
|
type: PendingTaskType.Backup,
|
||||||
@ -457,7 +481,8 @@ async function gatherBackupPending(
|
|||||||
});
|
});
|
||||||
} else if (bp.state.tag === BackupProviderStateTag.Retrying) {
|
} else if (bp.state.tag === BackupProviderStateTag.Retrying) {
|
||||||
const timestampDue =
|
const timestampDue =
|
||||||
retryRecord?.retryInfo?.nextRetry ?? AbsoluteTime.now();
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo?.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.Backup,
|
type: PendingTaskType.Backup,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -504,7 +529,8 @@ async function gatherPeerPullInitiationPending(
|
|||||||
const opId = TaskIdentifiers.forPeerPullPaymentInitiation(pi);
|
const opId = TaskIdentifiers.forPeerPullPaymentInitiation(pi);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue =
|
const timestampDue =
|
||||||
retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.PeerPullCredit,
|
type: PendingTaskType.PeerPullCredit,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -550,7 +576,8 @@ async function gatherPeerPullDebitPending(
|
|||||||
const opId = TaskIdentifiers.forPeerPullPaymentDebit(pi);
|
const opId = TaskIdentifiers.forPeerPullPaymentDebit(pi);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue =
|
const timestampDue =
|
||||||
retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.PeerPullDebit,
|
type: PendingTaskType.PeerPullDebit,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -596,7 +623,8 @@ async function gatherPeerPushInitiationPending(
|
|||||||
const opId = TaskIdentifiers.forPeerPushPaymentInitiation(pi);
|
const opId = TaskIdentifiers.forPeerPushPaymentInitiation(pi);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue =
|
const timestampDue =
|
||||||
retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.PeerPushDebit,
|
type: PendingTaskType.PeerPushDebit,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
@ -646,7 +674,8 @@ async function gatherPeerPushCreditPending(
|
|||||||
const opId = TaskIdentifiers.forPeerPushCredit(pi);
|
const opId = TaskIdentifiers.forPeerPushCredit(pi);
|
||||||
const retryRecord = await tx.operationRetries.get(opId);
|
const retryRecord = await tx.operationRetries.get(opId);
|
||||||
const timestampDue =
|
const timestampDue =
|
||||||
retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
|
timestampOptionalAbsoluteFromDb(retryRecord?.retryInfo.nextRetry) ??
|
||||||
|
AbsoluteTime.now();
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingTaskType.PeerPushCredit,
|
type: PendingTaskType.PeerPushCredit,
|
||||||
...getPendingCommon(ws, opId, timestampDue),
|
...getPendingCommon(ws, opId, timestampDue),
|
||||||
|
@ -81,6 +81,7 @@ import {
|
|||||||
PendingTaskType,
|
PendingTaskType,
|
||||||
RefreshSessionRecord,
|
RefreshSessionRecord,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import {
|
import {
|
||||||
EXCHANGE_COINS_LOCK,
|
EXCHANGE_COINS_LOCK,
|
||||||
@ -1125,10 +1126,10 @@ export async function createRefreshGroup(
|
|||||||
*/
|
*/
|
||||||
function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
|
function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
|
||||||
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
||||||
d.stampExpireWithdraw,
|
timestampProtocolFromDb(d.stampExpireWithdraw),
|
||||||
);
|
);
|
||||||
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
|
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
|
||||||
d.stampExpireDeposit,
|
timestampProtocolFromDb(d.stampExpireDeposit),
|
||||||
);
|
);
|
||||||
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
|
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
|
||||||
const deltaDiv = durationMul(delta, 0.75);
|
const deltaDiv = durationMul(delta, 0.75);
|
||||||
@ -1140,10 +1141,10 @@ function getAutoRefreshCheckThreshold(d: DenominationRecord): AbsoluteTime {
|
|||||||
*/
|
*/
|
||||||
function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
|
function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
|
||||||
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
const expireWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
||||||
d.stampExpireWithdraw,
|
timestampProtocolFromDb(d.stampExpireWithdraw),
|
||||||
);
|
);
|
||||||
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
|
const expireDeposit = AbsoluteTime.fromProtocolTimestamp(
|
||||||
d.stampExpireDeposit,
|
timestampProtocolFromDb(d.stampExpireDeposit),
|
||||||
);
|
);
|
||||||
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
|
const delta = AbsoluteTime.difference(expireWithdraw, expireDeposit);
|
||||||
const deltaDiv = durationMul(delta, 0.5);
|
const deltaDiv = durationMul(delta, 0.5);
|
||||||
@ -1227,8 +1228,9 @@ export async function autoRefresh(
|
|||||||
logger.trace(
|
logger.trace(
|
||||||
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
|
`next refresh check at ${AbsoluteTime.toIsoString(minCheckThreshold)}`,
|
||||||
);
|
);
|
||||||
exchange.nextRefreshCheckStampMs =
|
exchange.nextRefreshCheckStamp = timestampPreciseToDb(
|
||||||
AbsoluteTime.toStampMs(minCheckThreshold);
|
AbsoluteTime.toPreciseTimestamp(minCheckThreshold),
|
||||||
|
);
|
||||||
await tx.exchanges.put(exchange);
|
await tx.exchanges.put(exchange);
|
||||||
});
|
});
|
||||||
return TaskRunResult.finished();
|
return TaskRunResult.finished();
|
||||||
|
@ -52,6 +52,8 @@ import {
|
|||||||
RewardRecordStatus,
|
RewardRecordStatus,
|
||||||
timestampPreciseFromDb,
|
timestampPreciseFromDb,
|
||||||
timestampPreciseToDb,
|
timestampPreciseToDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
|
timestampProtocolToDb,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { makeErrorDetail } from "@gnu-taler/taler-util";
|
import { makeErrorDetail } from "@gnu-taler/taler-util";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
@ -201,7 +203,7 @@ export async function prepareTip(
|
|||||||
acceptedTimestamp: undefined,
|
acceptedTimestamp: undefined,
|
||||||
status: RewardRecordStatus.DialogAccept,
|
status: RewardRecordStatus.DialogAccept,
|
||||||
rewardAmountRaw: Amounts.stringify(amount),
|
rewardAmountRaw: Amounts.stringify(amount),
|
||||||
rewardExpiration: tipPickupStatus.expiration,
|
rewardExpiration: timestampProtocolToDb(tipPickupStatus.expiration),
|
||||||
exchangeBaseUrl: tipPickupStatus.exchange_url,
|
exchangeBaseUrl: tipPickupStatus.exchange_url,
|
||||||
next_url: tipPickupStatus.next_url,
|
next_url: tipPickupStatus.next_url,
|
||||||
merchantBaseUrl: res.merchantBaseUrl,
|
merchantBaseUrl: res.merchantBaseUrl,
|
||||||
@ -231,7 +233,7 @@ export async function prepareTip(
|
|||||||
rewardAmountRaw: Amounts.stringify(tipRecord.rewardAmountRaw),
|
rewardAmountRaw: Amounts.stringify(tipRecord.rewardAmountRaw),
|
||||||
exchangeBaseUrl: tipRecord.exchangeBaseUrl,
|
exchangeBaseUrl: tipRecord.exchangeBaseUrl,
|
||||||
merchantBaseUrl: tipRecord.merchantBaseUrl,
|
merchantBaseUrl: tipRecord.merchantBaseUrl,
|
||||||
expirationTimestamp: tipRecord.rewardExpiration,
|
expirationTimestamp: timestampProtocolFromDb(tipRecord.rewardExpiration),
|
||||||
rewardAmountEffective: Amounts.stringify(tipRecord.rewardAmountEffective),
|
rewardAmountEffective: Amounts.stringify(tipRecord.rewardAmountEffective),
|
||||||
walletRewardId: tipRecord.walletRewardId,
|
walletRewardId: tipRecord.walletRewardId,
|
||||||
transactionId,
|
transactionId,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
import {
|
import {
|
||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
Amounts,
|
Amounts,
|
||||||
|
DepositTransactionTrackingState,
|
||||||
j2s,
|
j2s,
|
||||||
Logger,
|
Logger,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
@ -69,6 +70,7 @@ import {
|
|||||||
GetReadOnlyAccess,
|
GetReadOnlyAccess,
|
||||||
timestampOptionalPreciseFromDb,
|
timestampOptionalPreciseFromDb,
|
||||||
timestampPreciseFromDb,
|
timestampPreciseFromDb,
|
||||||
|
timestampProtocolFromDb,
|
||||||
WalletStoresV1,
|
WalletStoresV1,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
@ -809,6 +811,17 @@ function buildTransactionForDeposit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trackingState: DepositTransactionTrackingState[] = [];
|
||||||
|
|
||||||
|
for (const ts of Object.values(dg.trackingState ?? {})) {
|
||||||
|
trackingState.push({
|
||||||
|
amountRaw: ts.amountRaw,
|
||||||
|
timestampExecuted: timestampProtocolFromDb(ts.timestampExecuted),
|
||||||
|
wireFee: ts.wireFee,
|
||||||
|
wireTransferId: ts.wireTransferId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: TransactionType.Deposit,
|
type: TransactionType.Deposit,
|
||||||
txState: computeDepositTransactionStatus(dg),
|
txState: computeDepositTransactionStatus(dg),
|
||||||
@ -817,7 +830,7 @@ function buildTransactionForDeposit(
|
|||||||
amountEffective: Amounts.stringify(dg.totalPayCost),
|
amountEffective: Amounts.stringify(dg.totalPayCost),
|
||||||
timestamp: timestampPreciseFromDb(dg.timestampCreated),
|
timestamp: timestampPreciseFromDb(dg.timestampCreated),
|
||||||
targetPaytoUri: dg.wire.payto_uri,
|
targetPaytoUri: dg.wire.payto_uri,
|
||||||
wireTransferDeadline: dg.wireTransferDeadline,
|
wireTransferDeadline: timestampProtocolFromDb(dg.wireTransferDeadline),
|
||||||
transactionId: constructTransactionIdentifier({
|
transactionId: constructTransactionIdentifier({
|
||||||
tag: TransactionType.Deposit,
|
tag: TransactionType.Deposit,
|
||||||
depositGroupId: dg.depositGroupId,
|
depositGroupId: dg.depositGroupId,
|
||||||
@ -830,7 +843,7 @@ function buildTransactionForDeposit(
|
|||||||
)) /
|
)) /
|
||||||
dg.statusPerCoin.length,
|
dg.statusPerCoin.length,
|
||||||
depositGroupId: dg.depositGroupId,
|
depositGroupId: dg.depositGroupId,
|
||||||
trackingState: Object.values(dg.trackingState ?? {}),
|
trackingState,
|
||||||
deposited,
|
deposited,
|
||||||
...(ort?.lastError ? { error: ort.lastError } : {}),
|
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
import { Amounts, DenomKeyType } from "@gnu-taler/taler-util";
|
import { Amounts, DenomKeyType } from "@gnu-taler/taler-util";
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import { DenominationRecord, DenominationVerificationStatus } from "../db.js";
|
import {
|
||||||
|
DenominationRecord,
|
||||||
|
DenominationVerificationStatus,
|
||||||
|
timestampProtocolToDb,
|
||||||
|
} from "../db.js";
|
||||||
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
|
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
|
||||||
|
|
||||||
test("withdrawal selection bug repro", (t) => {
|
test("withdrawal selection bug repro", (t) => {
|
||||||
@ -64,22 +68,22 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"4F0P456CNNTTWK8BFJHGM3JTD6FVVNZY8EP077GYAHDJ5Y81S5RQ3SMS925NXMDVG9A88JAAP0E2GDZBC21PP5NHFFVWHAW3AVT8J3R",
|
"4F0P456CNNTTWK8BFJHGM3JTD6FVVNZY8EP077GYAHDJ5Y81S5RQ3SMS925NXMDVG9A88JAAP0E2GDZBC21PP5NHFFVWHAW3AVT8J3R",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
value: "KUDOS:1000",
|
value: "KUDOS:1000",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
denomPub: {
|
denomPub: {
|
||||||
@ -119,22 +123,22 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"P99AW82W46MZ0AKW7Z58VQPXFNTJQM9DVTYPBDF6KVYF38PPVDAZTV7JQ8TY7HGEC7JJJAY4E7AY7J3W1WV10DAZZQHHKTAVTSRAC20",
|
"P99AW82W46MZ0AKW7Z58VQPXFNTJQM9DVTYPBDF6KVYF38PPVDAZTV7JQ8TY7HGEC7JJJAY4E7AY7J3W1WV10DAZZQHHKTAVTSRAC20",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: "KUDOS:10",
|
value: "KUDOS:10",
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
denomPub: {
|
denomPub: {
|
||||||
@ -173,22 +177,22 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"8S4VZGHE5WE0N5ZVCHYW9KZZR4YAKK15S46MV1HR1QB9AAMH3NWPW4DCR4NYGJK33Q8YNFY80SWNS6XKAP5DEVK933TM894FJ2VGE3G",
|
"8S4VZGHE5WE0N5ZVCHYW9KZZR4YAKK15S46MV1HR1QB9AAMH3NWPW4DCR4NYGJK33Q8YNFY80SWNS6XKAP5DEVK933TM894FJ2VGE3G",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: "KUDOS:5",
|
value: "KUDOS:5",
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
denomPub: {
|
denomPub: {
|
||||||
@ -228,22 +232,22 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"E3AWGAG8VB42P3KXM8B04Z6M483SX59R3Y4T53C3NXCA2NPB6C7HVCMVX05DC6S58E9X40NGEBQNYXKYMYCF3ASY2C4WP1WCZ4ME610",
|
"E3AWGAG8VB42P3KXM8B04Z6M483SX59R3Y4T53C3NXCA2NPB6C7HVCMVX05DC6S58E9X40NGEBQNYXKYMYCF3ASY2C4WP1WCZ4ME610",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: "KUDOS:1",
|
value: "KUDOS:1",
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
denomPub: {
|
denomPub: {
|
||||||
@ -282,18 +286,18 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"0ES1RKV002XB4YP21SN0QB7RSDHGYT0XAE65JYN8AVJAA6H7JZFN7JADXT521DJS89XMGPZGR8GCXF1516Y0Q9QDV00E6NMFA6CF838",
|
"0ES1RKV002XB4YP21SN0QB7RSDHGYT0XAE65JYN8AVJAA6H7JZFN7JADXT521DJS89XMGPZGR8GCXF1516Y0Q9QDV00E6NMFA6CF838",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: Amounts.stringify({
|
value: Amounts.stringify({
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
@ -301,7 +305,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
value: 0,
|
value: 0,
|
||||||
}),
|
}),
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
denomPub: {
|
denomPub: {
|
||||||
@ -340,22 +344,22 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
isRevoked: false,
|
isRevoked: false,
|
||||||
masterSig:
|
masterSig:
|
||||||
"58QEB6C6N7602E572E3JYANVVJ9BRW0V9E2ZFDW940N47YVQDK9SAFPWBN5YGT3G1742AFKQ0CYR4DM2VWV0Z0T1XMEKWN6X2EZ9M0R",
|
"58QEB6C6N7602E572E3JYANVVJ9BRW0V9E2ZFDW940N47YVQDK9SAFPWBN5YGT3G1742AFKQ0CYR4DM2VWV0Z0T1XMEKWN6X2EZ9M0R",
|
||||||
stampExpireDeposit: {
|
stampExpireDeposit: timestampProtocolToDb({
|
||||||
t_s: 1742909388,
|
t_s: 1742909388,
|
||||||
},
|
}),
|
||||||
stampExpireLegal: {
|
stampExpireLegal: timestampProtocolToDb({
|
||||||
t_s: 1900589388,
|
t_s: 1900589388,
|
||||||
},
|
}),
|
||||||
stampExpireWithdraw: {
|
stampExpireWithdraw: timestampProtocolToDb({
|
||||||
t_s: 1679837388,
|
t_s: 1679837388,
|
||||||
},
|
}),
|
||||||
stampStart: {
|
stampStart: timestampProtocolToDb({
|
||||||
t_s: 1585229388,
|
t_s: 1585229388,
|
||||||
},
|
}),
|
||||||
verificationStatus: DenominationVerificationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: "KUDOS:2",
|
value: "KUDOS:2",
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
listIssueDate: { t_s: 0 },
|
listIssueDate: timestampProtocolToDb({ t_s: 0 }),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { TalerErrorDetail, AbsoluteTime } from "@gnu-taler/taler-util";
|
import { TalerErrorDetail, AbsoluteTime } from "@gnu-taler/taler-util";
|
||||||
import { RetryInfo } from "./operations/common.js";
|
import { DbRetryInfo } from "./operations/common.js";
|
||||||
|
|
||||||
export enum PendingTaskType {
|
export enum PendingTaskType {
|
||||||
ExchangeUpdate = "exchange-update",
|
ExchangeUpdate = "exchange-update",
|
||||||
@ -137,7 +137,7 @@ export interface PendingRefreshTask {
|
|||||||
lastError?: TalerErrorDetail;
|
lastError?: TalerErrorDetail;
|
||||||
refreshGroupId: string;
|
refreshGroupId: string;
|
||||||
finishedPerCoin: boolean[];
|
finishedPerCoin: boolean[];
|
||||||
retryInfo?: RetryInfo;
|
retryInfo?: DbRetryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +156,7 @@ export interface PendingTipPickupTask {
|
|||||||
export interface PendingPurchaseTask {
|
export interface PendingPurchaseTask {
|
||||||
type: PendingTaskType.Purchase;
|
type: PendingTaskType.Purchase;
|
||||||
proposalId: string;
|
proposalId: string;
|
||||||
retryInfo?: RetryInfo;
|
retryInfo?: DbRetryInfo;
|
||||||
/**
|
/**
|
||||||
* Status of the payment as string, used only for debugging.
|
* Status of the payment as string, used only for debugging.
|
||||||
*/
|
*/
|
||||||
@ -167,7 +167,7 @@ export interface PendingPurchaseTask {
|
|||||||
export interface PendingRecoupTask {
|
export interface PendingRecoupTask {
|
||||||
type: PendingTaskType.Recoup;
|
type: PendingTaskType.Recoup;
|
||||||
recoupGroupId: string;
|
recoupGroupId: string;
|
||||||
retryInfo?: RetryInfo;
|
retryInfo?: DbRetryInfo;
|
||||||
lastError: TalerErrorDetail | undefined;
|
lastError: TalerErrorDetail | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ export interface PendingRecoupTask {
|
|||||||
export interface PendingWithdrawTask {
|
export interface PendingWithdrawTask {
|
||||||
type: PendingTaskType.Withdraw;
|
type: PendingTaskType.Withdraw;
|
||||||
lastError: TalerErrorDetail | undefined;
|
lastError: TalerErrorDetail | undefined;
|
||||||
retryInfo?: RetryInfo;
|
retryInfo?: DbRetryInfo;
|
||||||
withdrawalGroupId: string;
|
withdrawalGroupId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ export interface PendingWithdrawTask {
|
|||||||
export interface PendingDepositTask {
|
export interface PendingDepositTask {
|
||||||
type: PendingTaskType.Deposit;
|
type: PendingTaskType.Deposit;
|
||||||
lastError: TalerErrorDetail | undefined;
|
lastError: TalerErrorDetail | undefined;
|
||||||
retryInfo: RetryInfo | undefined;
|
retryInfo: DbRetryInfo | undefined;
|
||||||
depositGroupId: string;
|
depositGroupId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ export interface PendingTaskInfoCommon {
|
|||||||
* Retry info. Currently used to stop the wallet after any operation
|
* Retry info. Currently used to stop the wallet after any operation
|
||||||
* exceeds a number of retries.
|
* exceeds a number of retries.
|
||||||
*/
|
*/
|
||||||
retryInfo?: RetryInfo;
|
retryInfo?: DbRetryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,10 +26,9 @@ import {
|
|||||||
FeeDescriptionPair,
|
FeeDescriptionPair,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
TimePoint,
|
TimePoint,
|
||||||
WireFee,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { DenominationRecord } from "../db.js";
|
import { DenominationRecord } from "../db.js";
|
||||||
import { WalletConfig } from "../index.js";
|
import { timestampProtocolFromDb } from "../index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of denominations with the same value and same period of time:
|
* Given a list of denominations with the same value and same period of time:
|
||||||
@ -457,9 +456,11 @@ export function isWithdrawableDenom(
|
|||||||
denomselAllowLate?: boolean,
|
denomselAllowLate?: boolean,
|
||||||
): boolean {
|
): boolean {
|
||||||
const now = AbsoluteTime.now();
|
const now = AbsoluteTime.now();
|
||||||
const start = AbsoluteTime.fromProtocolTimestamp(d.stampStart);
|
const start = AbsoluteTime.fromProtocolTimestamp(
|
||||||
|
timestampProtocolFromDb(d.stampStart),
|
||||||
|
);
|
||||||
const withdrawExpire = AbsoluteTime.fromProtocolTimestamp(
|
const withdrawExpire = AbsoluteTime.fromProtocolTimestamp(
|
||||||
d.stampExpireWithdraw,
|
timestampProtocolFromDb(d.stampExpireWithdraw),
|
||||||
);
|
);
|
||||||
const started = AbsoluteTime.cmp(now, start) >= 0;
|
const started = AbsoluteTime.cmp(now, start) >= 0;
|
||||||
let lastPossibleWithdraw: AbsoluteTime;
|
let lastPossibleWithdraw: AbsoluteTime;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { GlobalIDB } from "@gnu-taler/idb-bridge";
|
||||||
import {
|
import {
|
||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
AgeRestriction,
|
AgeRestriction,
|
||||||
@ -29,14 +30,14 @@ import {
|
|||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
strcmp,
|
strcmp,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { checkDbInvariant } from "./invariants.js";
|
|
||||||
import {
|
import {
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
InternalWalletState,
|
InternalWalletState,
|
||||||
getExchangeDetails,
|
getExchangeDetails,
|
||||||
|
timestampProtocolFromDb,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { CoinInfo } from "./coinSelection.js";
|
import { CoinInfo } from "./coinSelection.js";
|
||||||
import { GlobalIDB } from "@gnu-taler/idb-bridge";
|
import { checkDbInvariant } from "./invariants.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the operation going to be plan subtracts
|
* If the operation going to be plan subtracts
|
||||||
@ -224,10 +225,10 @@ async function getAvailableDenoms(
|
|||||||
);
|
);
|
||||||
for (const denom of ds) {
|
for (const denom of ds) {
|
||||||
const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
||||||
denom.stampExpireWithdraw,
|
timestampProtocolFromDb(denom.stampExpireWithdraw),
|
||||||
);
|
);
|
||||||
const expiresDeposit = AbsoluteTime.fromProtocolTimestamp(
|
const expiresDeposit = AbsoluteTime.fromProtocolTimestamp(
|
||||||
denom.stampExpireDeposit,
|
timestampProtocolFromDb(denom.stampExpireDeposit),
|
||||||
);
|
);
|
||||||
creditDeadline = AbsoluteTime.min(deadline, expiresWithdraw);
|
creditDeadline = AbsoluteTime.min(deadline, expiresWithdraw);
|
||||||
debitDeadline = AbsoluteTime.min(deadline, expiresDeposit);
|
debitDeadline = AbsoluteTime.min(deadline, expiresDeposit);
|
||||||
@ -270,10 +271,10 @@ async function getAvailableDenoms(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
const expiresWithdraw = AbsoluteTime.fromProtocolTimestamp(
|
||||||
denom.stampExpireWithdraw,
|
timestampProtocolFromDb(denom.stampExpireWithdraw),
|
||||||
);
|
);
|
||||||
const expiresDeposit = AbsoluteTime.fromProtocolTimestamp(
|
const expiresDeposit = AbsoluteTime.fromProtocolTimestamp(
|
||||||
denom.stampExpireDeposit,
|
timestampProtocolFromDb(denom.stampExpireDeposit),
|
||||||
);
|
);
|
||||||
creditDeadline = AbsoluteTime.min(deadline, expiresWithdraw);
|
creditDeadline = AbsoluteTime.min(deadline, expiresWithdraw);
|
||||||
debitDeadline = AbsoluteTime.min(deadline, expiresDeposit);
|
debitDeadline = AbsoluteTime.min(deadline, expiresDeposit);
|
||||||
@ -318,7 +319,9 @@ function buildCoinInfoFromDenom(
|
|||||||
exchangeBaseUrl: denom.exchangeBaseUrl,
|
exchangeBaseUrl: denom.exchangeBaseUrl,
|
||||||
duration: AbsoluteTime.difference(
|
duration: AbsoluteTime.difference(
|
||||||
AbsoluteTime.now(),
|
AbsoluteTime.now(),
|
||||||
AbsoluteTime.fromProtocolTimestamp(denom.stampExpireDeposit),
|
AbsoluteTime.fromProtocolTimestamp(
|
||||||
|
timestampProtocolFromDb(denom.stampExpireDeposit),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
totalAvailable: total,
|
totalAvailable: total,
|
||||||
value: Amounts.parseOrThrow(denom.value),
|
value: Amounts.parseOrThrow(denom.value),
|
||||||
|
Loading…
Reference in New Issue
Block a user