wallet-core: allow inclusion of refreshes in transactions list
This commit is contained in:
parent
97fac057c2
commit
55f868d5e8
@ -68,6 +68,11 @@ export interface TransactionsRequest {
|
|||||||
* if present, results will be limited to transactions related to the given search string
|
* if present, results will be limited to transactions related to the given search string
|
||||||
*/
|
*/
|
||||||
search?: string;
|
search?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, include all refreshes in the transactions list.
|
||||||
|
*/
|
||||||
|
includeRefreshes?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionsResponse {
|
export interface TransactionsResponse {
|
||||||
@ -514,11 +519,6 @@ export interface TransactionTip extends TransactionCommon {
|
|||||||
export interface TransactionRefresh extends TransactionCommon {
|
export interface TransactionRefresh extends TransactionCommon {
|
||||||
type: TransactionType.Refresh;
|
type: TransactionType.Refresh;
|
||||||
|
|
||||||
/**
|
|
||||||
* Exchange that the coins are refreshed with
|
|
||||||
*/
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
refreshReason: RefreshReason;
|
refreshReason: RefreshReason;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -381,7 +381,8 @@ walletCli
|
|||||||
const transactionsCli = walletCli
|
const transactionsCli = walletCli
|
||||||
.subcommand("transactions", "transactions", { help: "Manage transactions." })
|
.subcommand("transactions", "transactions", { help: "Manage transactions." })
|
||||||
.maybeOption("currency", ["--currency"], clk.STRING)
|
.maybeOption("currency", ["--currency"], clk.STRING)
|
||||||
.maybeOption("search", ["--search"], clk.STRING);
|
.maybeOption("search", ["--search"], clk.STRING)
|
||||||
|
.flag("includeRefreshes", ["--include-refreshes"]);
|
||||||
|
|
||||||
// Default action
|
// Default action
|
||||||
transactionsCli.action(async (args) => {
|
transactionsCli.action(async (args) => {
|
||||||
@ -391,6 +392,7 @@ transactionsCli.action(async (args) => {
|
|||||||
{
|
{
|
||||||
currency: args.transactions.currency,
|
currency: args.transactions.currency,
|
||||||
search: args.transactions.search,
|
search: args.transactions.search,
|
||||||
|
includeRefreshes: args.transactions.includeRefreshes,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
console.log(JSON.stringify(pending, undefined, 2));
|
console.log(JSON.stringify(pending, undefined, 2));
|
||||||
|
@ -56,6 +56,8 @@ import {
|
|||||||
PeerPullPaymentIncomingStatus,
|
PeerPullPaymentIncomingStatus,
|
||||||
TransactionStatus,
|
TransactionStatus,
|
||||||
WithdrawalGroupStatus,
|
WithdrawalGroupStatus,
|
||||||
|
RefreshGroupRecord,
|
||||||
|
RefreshOperationStatus,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { checkDbInvariant } from "../util/invariants.js";
|
import { checkDbInvariant } from "../util/invariants.js";
|
||||||
@ -580,6 +582,45 @@ function buildTransactionForManualWithdraw(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildTransactionForRefresh(
|
||||||
|
refreshGroupRecord: RefreshGroupRecord,
|
||||||
|
ort?: OperationRetryRecord,
|
||||||
|
): Transaction {
|
||||||
|
let extendedStatus: ExtendedStatus;
|
||||||
|
switch (refreshGroupRecord.operationStatus) {
|
||||||
|
case RefreshOperationStatus.Finished:
|
||||||
|
case RefreshOperationStatus.FinishedWithError:
|
||||||
|
extendedStatus = ExtendedStatus.Done;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
extendedStatus = ExtendedStatus.Pending;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: TransactionType.Refresh,
|
||||||
|
refreshReason: refreshGroupRecord.reason,
|
||||||
|
amountEffective: Amounts.stringify(
|
||||||
|
Amounts.zeroOfCurrency(refreshGroupRecord.currency),
|
||||||
|
),
|
||||||
|
amountRaw: Amounts.stringify(
|
||||||
|
Amounts.zeroOfCurrency(refreshGroupRecord.currency),
|
||||||
|
),
|
||||||
|
extendedStatus:
|
||||||
|
refreshGroupRecord.operationStatus === RefreshOperationStatus.Finished ||
|
||||||
|
refreshGroupRecord.operationStatus ===
|
||||||
|
RefreshOperationStatus.FinishedWithError
|
||||||
|
? ExtendedStatus.Done
|
||||||
|
: ExtendedStatus.Pending,
|
||||||
|
pending: extendedStatus == ExtendedStatus.Pending,
|
||||||
|
timestamp: refreshGroupRecord.timestampCreated,
|
||||||
|
transactionId: makeTransactionId(
|
||||||
|
TransactionType.Refresh,
|
||||||
|
refreshGroupRecord.refreshGroupId,
|
||||||
|
),
|
||||||
|
frozen: false,
|
||||||
|
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildTransactionForDeposit(
|
function buildTransactionForDeposit(
|
||||||
dg: DepositGroupRecord,
|
dg: DepositGroupRecord,
|
||||||
ort?: OperationRetryRecord,
|
ort?: OperationRetryRecord,
|
||||||
@ -880,6 +921,7 @@ export async function getTransactions(
|
|||||||
x.tips,
|
x.tips,
|
||||||
x.tombstones,
|
x.tombstones,
|
||||||
x.withdrawalGroups,
|
x.withdrawalGroups,
|
||||||
|
x.refreshGroups,
|
||||||
])
|
])
|
||||||
.runReadOnly(async (tx) => {
|
.runReadOnly(async (tx) => {
|
||||||
tx.peerPushPaymentInitiations.iter().forEachAsync(async (pi) => {
|
tx.peerPushPaymentInitiations.iter().forEachAsync(async (pi) => {
|
||||||
@ -916,6 +958,17 @@ export async function getTransactions(
|
|||||||
transactions.push(buildTransactionForPullPaymentDebit(pi));
|
transactions.push(buildTransactionForPullPaymentDebit(pi));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (transactionsRequest?.includeRefreshes) {
|
||||||
|
tx.refreshGroups.iter().forEachAsync(async (rg) => {
|
||||||
|
if (shouldSkipCurrency(transactionsRequest, rg.currency)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const opId = RetryTags.forRefresh(rg);
|
||||||
|
const ort = await tx.operationRetries.get(opId);
|
||||||
|
transactions.push(buildTransactionForRefresh(rg, ort));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
tx.withdrawalGroups.iter().forEachAsync(async (wsr) => {
|
tx.withdrawalGroups.iter().forEachAsync(async (wsr) => {
|
||||||
if (
|
if (
|
||||||
shouldSkipCurrency(
|
shouldSkipCurrency(
|
||||||
|
@ -110,7 +110,7 @@ export function TransactionItem(props: { tx: Transaction }): VNode {
|
|||||||
id={tx.transactionId}
|
id={tx.transactionId}
|
||||||
amount={tx.amountEffective}
|
amount={tx.amountEffective}
|
||||||
debitCreditIndicator={"credit"}
|
debitCreditIndicator={"credit"}
|
||||||
title={new URL(tx.exchangeBaseUrl).hostname}
|
title={"Refresh"}
|
||||||
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
|
timestamp={AbsoluteTime.fromTimestamp(tx.timestamp)}
|
||||||
iconPath={"R"}
|
iconPath={"R"}
|
||||||
// pending={tx.pending}
|
// pending={tx.pending}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
PaymentStatus,
|
PaymentStatus,
|
||||||
|
RefreshReason,
|
||||||
ScopeType,
|
ScopeType,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
TransactionCommon,
|
TransactionCommon,
|
||||||
@ -90,6 +91,7 @@ const exampleData = {
|
|||||||
totalRefundRaw: "USD:0",
|
totalRefundRaw: "USD:0",
|
||||||
proposalId: "1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
|
proposalId: "1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
|
||||||
status: PaymentStatus.Accepted,
|
status: PaymentStatus.Accepted,
|
||||||
|
refundQueryActive: false,
|
||||||
} as TransactionPayment,
|
} as TransactionPayment,
|
||||||
deposit: {
|
deposit: {
|
||||||
...commonTransaction(),
|
...commonTransaction(),
|
||||||
@ -101,6 +103,7 @@ const exampleData = {
|
|||||||
...commonTransaction(),
|
...commonTransaction(),
|
||||||
type: TransactionType.Refresh,
|
type: TransactionType.Refresh,
|
||||||
exchangeBaseUrl: "http://exchange.taler",
|
exchangeBaseUrl: "http://exchange.taler",
|
||||||
|
refreshReason: RefreshReason.PayMerchant,
|
||||||
} as TransactionRefresh,
|
} as TransactionRefresh,
|
||||||
tip: {
|
tip: {
|
||||||
...commonTransaction(),
|
...commonTransaction(),
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
ExtendedStatus,
|
ExtendedStatus,
|
||||||
PaymentStatus,
|
PaymentStatus,
|
||||||
|
RefreshReason,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
TransactionCommon,
|
TransactionCommon,
|
||||||
TransactionDeposit,
|
TransactionDeposit,
|
||||||
@ -111,6 +112,7 @@ const exampleData = {
|
|||||||
totalRefundRaw: "KUDOS:0",
|
totalRefundRaw: "KUDOS:0",
|
||||||
proposalId: "1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
|
proposalId: "1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
|
||||||
status: PaymentStatus.Accepted,
|
status: PaymentStatus.Accepted,
|
||||||
|
refundQueryActive: false,
|
||||||
} as TransactionPayment,
|
} as TransactionPayment,
|
||||||
deposit: {
|
deposit: {
|
||||||
...commonTransaction,
|
...commonTransaction,
|
||||||
@ -125,6 +127,7 @@ const exampleData = {
|
|||||||
...commonTransaction,
|
...commonTransaction,
|
||||||
type: TransactionType.Refresh,
|
type: TransactionType.Refresh,
|
||||||
exchangeBaseUrl: "http://exchange.taler",
|
exchangeBaseUrl: "http://exchange.taler",
|
||||||
|
refreshReason: RefreshReason.Manual,
|
||||||
} as TransactionRefresh,
|
} as TransactionRefresh,
|
||||||
tip: {
|
tip: {
|
||||||
...commonTransaction,
|
...commonTransaction,
|
||||||
|
@ -729,7 +729,7 @@ export function TransactionView({
|
|||||||
total={effective}
|
total={effective}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
>
|
>
|
||||||
{transaction.exchangeBaseUrl}
|
{"Refresh"}
|
||||||
</Header>
|
</Header>
|
||||||
<Part
|
<Part
|
||||||
title={i18n.str`Details`}
|
title={i18n.str`Details`}
|
||||||
|
Loading…
Reference in New Issue
Block a user