wallet-core: properly separate different types of IDs
This commit is contained in:
parent
eec6695be0
commit
0c8e56c324
@ -73,12 +73,14 @@ import { VersionMatchResult } from "./libtool-version.js";
|
||||
/**
|
||||
* Identifier for a transaction in the wallet.
|
||||
*/
|
||||
export type TransactionIdStr = `tx:${string}:${string}`;
|
||||
export type TransactionIdStr = `txn:${string}:${string}`;
|
||||
|
||||
/**
|
||||
* Identifier for a pending task in the wallet.
|
||||
*/
|
||||
export type PendingIdStr = `pd:${string}:string`;
|
||||
export type PendingIdStr = `pnd:${string}:${string}`;
|
||||
|
||||
export type TombstoneIdStr = `tmb:${string}:${string}`;
|
||||
|
||||
/**
|
||||
* Response for the create reserve request to the wallet.
|
||||
|
@ -63,7 +63,7 @@ import { InternalWalletState } from "../../internal-wallet-state.js";
|
||||
import { assertUnreachable } from "../../util/assertUnreachable.js";
|
||||
import { checkLogicInvariant } from "../../util/invariants.js";
|
||||
import { GetReadOnlyAccess, GetReadWriteAccess } from "../../util/query.js";
|
||||
import { makeCoinAvailable, makeEventId, TombstoneTag } from "../common.js";
|
||||
import { makeCoinAvailable, makeTombstoneId, makeTransactionId, TombstoneTag } from "../common.js";
|
||||
import { getExchangeDetails } from "../exchanges.js";
|
||||
import { extractContractData } from "../pay-merchant.js";
|
||||
import { provideBackupState } from "./state.js";
|
||||
@ -493,7 +493,7 @@ export async function importBackup(
|
||||
for (const backupWg of backupBlob.withdrawal_groups) {
|
||||
const reservePub = cryptoComp.reservePrivToPub[backupWg.reserve_priv];
|
||||
checkLogicInvariant(!!reservePub);
|
||||
const ts = makeEventId(TombstoneTag.DeleteReserve, reservePub);
|
||||
const ts = makeTombstoneId(TombstoneTag.DeleteReserve, reservePub);
|
||||
if (tombstoneSet.has(ts)) {
|
||||
continue;
|
||||
}
|
||||
@ -574,7 +574,7 @@ export async function importBackup(
|
||||
}
|
||||
|
||||
for (const backupPurchase of backupBlob.purchases) {
|
||||
const ts = makeEventId(
|
||||
const ts = makeTombstoneId(
|
||||
TombstoneTag.DeletePayment,
|
||||
backupPurchase.proposal_id,
|
||||
);
|
||||
@ -705,7 +705,7 @@ export async function importBackup(
|
||||
}
|
||||
|
||||
for (const backupRefreshGroup of backupBlob.refresh_groups) {
|
||||
const ts = makeEventId(
|
||||
const ts = makeTombstoneId(
|
||||
TombstoneTag.DeleteRefreshGroup,
|
||||
backupRefreshGroup.refresh_group_id,
|
||||
);
|
||||
@ -791,7 +791,7 @@ export async function importBackup(
|
||||
}
|
||||
|
||||
for (const backupTip of backupBlob.tips) {
|
||||
const ts = makeEventId(TombstoneTag.DeleteTip, backupTip.wallet_tip_id);
|
||||
const ts = makeTombstoneId(TombstoneTag.DeleteTip, backupTip.wallet_tip_id);
|
||||
if (tombstoneSet.has(ts)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
RefreshReason,
|
||||
TalerErrorCode,
|
||||
TalerErrorDetail,
|
||||
TombstoneIdStr,
|
||||
TransactionIdStr,
|
||||
TransactionType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
@ -280,9 +281,19 @@ export enum TombstoneTag {
|
||||
/**
|
||||
* Create an event ID from the type and the primary key for the event.
|
||||
*/
|
||||
export function makeEventId(
|
||||
type: TransactionType | TombstoneTag,
|
||||
export function makeTransactionId(
|
||||
type: TransactionType,
|
||||
...args: string[]
|
||||
): string {
|
||||
return type + ":" + args.map((x) => encodeURIComponent(x)).join(":");
|
||||
): TransactionIdStr {
|
||||
return `txn:${type}:${args.map((x) => encodeURIComponent(x)).join(":")}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an event ID from the type and the primary key for the event.
|
||||
*/
|
||||
export function makeTombstoneId(
|
||||
type: TombstoneTag,
|
||||
...args: string[]
|
||||
): TombstoneIdStr {
|
||||
return `tmb:${type}:${args.map((x) => encodeURIComponent(x)).join(":")}`;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ import {
|
||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
||||
import { OperationAttemptResult } from "../util/retries.js";
|
||||
import { makeEventId, spendCoins } from "./common.js";
|
||||
import { makeTransactionId, spendCoins } from "./common.js";
|
||||
import { getExchangeDetails } from "./exchanges.js";
|
||||
import {
|
||||
extractContractData,
|
||||
@ -495,7 +495,7 @@ export async function createDepositGroup(
|
||||
])
|
||||
.runReadWrite(async (tx) => {
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `deposit-group:${depositGroup.depositGroupId}`,
|
||||
allocationId: `txn:deposit:${depositGroup.depositGroupId}`,
|
||||
coinPubs: payCoinSel.coinPubs,
|
||||
contributions: payCoinSel.coinContributions,
|
||||
refreshReason: RefreshReason.PayDeposit,
|
||||
@ -505,7 +505,7 @@ export async function createDepositGroup(
|
||||
|
||||
return {
|
||||
depositGroupId: depositGroupId,
|
||||
transactionId: makeEventId(TransactionType.Deposit, depositGroupId),
|
||||
transactionId: makeTransactionId(TransactionType.Deposit, depositGroupId),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ import {
|
||||
scheduleRetry,
|
||||
} from "../util/retries.js";
|
||||
import {
|
||||
makeEventId,
|
||||
makeTransactionId,
|
||||
spendCoins,
|
||||
storeOperationError,
|
||||
storeOperationPending,
|
||||
@ -858,7 +858,7 @@ async function handleInsufficientFunds(
|
||||
payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(32));
|
||||
await tx.purchases.put(p);
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `tx:proposal:${p.proposalId}`,
|
||||
allocationId: `txn:proposal:${p.proposalId}`,
|
||||
coinPubs: payInfo.payCoinSelection.coinPubs,
|
||||
contributions: payInfo.payCoinSelection.coinContributions,
|
||||
refreshReason: RefreshReason.PayMerchant,
|
||||
@ -1554,7 +1554,7 @@ export async function runPayForConfirmPay(
|
||||
return {
|
||||
type: ConfirmPayResultType.Done,
|
||||
contractTerms: d.contractTermsRaw,
|
||||
transactionId: makeEventId(TransactionType.Payment, proposalId),
|
||||
transactionId: makeTransactionId(TransactionType.Payment, proposalId),
|
||||
};
|
||||
}
|
||||
case OperationAttemptResultType.Error: {
|
||||
@ -1580,7 +1580,7 @@ export async function runPayForConfirmPay(
|
||||
return {
|
||||
type: ConfirmPayResultType.Pending,
|
||||
lastError: opRetry?.lastError,
|
||||
transactionId: makeEventId(TransactionType.Payment, proposalId),
|
||||
transactionId: makeTransactionId(TransactionType.Payment, proposalId),
|
||||
};
|
||||
} else {
|
||||
// FIXME: allocate error code!
|
||||
@ -1599,7 +1599,7 @@ export async function runPayForConfirmPay(
|
||||
);
|
||||
return {
|
||||
type: ConfirmPayResultType.Pending,
|
||||
transactionId: makeEventId(TransactionType.Payment, proposalId),
|
||||
transactionId: makeTransactionId(TransactionType.Payment, proposalId),
|
||||
lastError: undefined,
|
||||
};
|
||||
case OperationAttemptResultType.Longpoll:
|
||||
@ -1735,7 +1735,7 @@ export async function confirmPay(
|
||||
p.purchaseStatus = PurchaseStatus.Paying;
|
||||
await tx.purchases.put(p);
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `tx:proposal:${p.proposalId}`,
|
||||
allocationId: `txn:proposal:${p.proposalId}`,
|
||||
coinPubs: coinSelection.coinPubs,
|
||||
contributions: coinSelection.coinContributions,
|
||||
refreshReason: RefreshReason.PayMerchant,
|
||||
@ -2549,7 +2549,7 @@ export async function applyRefundFromPurchaseId(
|
||||
return {
|
||||
contractTermsHash: download.contractData.contractTermsHash,
|
||||
proposalId: purchase.proposalId,
|
||||
transactionId: makeEventId(TransactionType.Payment, proposalId), //FIXME: can we have the tx id of the refund
|
||||
transactionId: makeTransactionId(TransactionType.Payment, proposalId), //FIXME: can we have the tx id of the refund
|
||||
amountEffectivePaid: Amounts.stringify(summary.amountEffectivePaid),
|
||||
amountRefundGone: Amounts.stringify(summary.amountRefundGone),
|
||||
amountRefundGranted: Amounts.stringify(summary.amountRefundGranted),
|
||||
|
@ -73,7 +73,7 @@ import { InternalWalletState } from "../internal-wallet-state.js";
|
||||
import { readSuccessResponseJsonOrThrow } from "../util/http.js";
|
||||
import { checkDbInvariant } from "../util/invariants.js";
|
||||
import { GetReadOnlyAccess } from "../util/query.js";
|
||||
import { spendCoins, makeEventId } from "../operations/common.js";
|
||||
import { spendCoins, makeTransactionId } from "../operations/common.js";
|
||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||
import { internalCreateWithdrawalGroup } from "./withdraw.js";
|
||||
|
||||
@ -261,7 +261,7 @@ export async function initiatePeerToPeerPush(
|
||||
}
|
||||
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `peer-push:${pursePair.pub}`,
|
||||
allocationId: `txn:peer-push-debit:${pursePair.pub}`,
|
||||
coinPubs: sel.coins.map((x) => x.coinPub),
|
||||
contributions: sel.coins.map((x) =>
|
||||
Amounts.parseOrThrow(x.contribution),
|
||||
@ -340,7 +340,7 @@ export async function initiatePeerToPeerPush(
|
||||
exchangeBaseUrl: coinSelRes.exchangeBaseUrl,
|
||||
contractPriv: econtractResp.contractPriv,
|
||||
}),
|
||||
transactionId: makeEventId(TransactionType.PeerPushDebit, pursePair.pub),
|
||||
transactionId: makeTransactionId(TransactionType.PeerPushDebit, pursePair.pub),
|
||||
};
|
||||
}
|
||||
|
||||
@ -551,7 +551,7 @@ export async function acceptPeerPushPayment(
|
||||
});
|
||||
|
||||
return {
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPushCredit,
|
||||
wg.withdrawalGroupId,
|
||||
),
|
||||
@ -596,7 +596,7 @@ export async function acceptPeerPullPayment(
|
||||
}
|
||||
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `peer-pull:${req.peerPullPaymentIncomingId}`,
|
||||
allocationId: `txn:peer-pull-debit:${req.peerPullPaymentIncomingId}`,
|
||||
coinPubs: sel.coins.map((x) => x.coinPub),
|
||||
contributions: sel.coins.map((x) =>
|
||||
Amounts.parseOrThrow(x.contribution),
|
||||
@ -643,7 +643,7 @@ export async function acceptPeerPullPayment(
|
||||
logger.trace(`purse deposit response: ${j2s(resp)}`);
|
||||
|
||||
return {
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPullDebit,
|
||||
req.peerPullPaymentIncomingId,
|
||||
),
|
||||
@ -839,7 +839,7 @@ export async function initiatePeerRequestForPay(
|
||||
exchangeBaseUrl: req.exchangeBaseUrl,
|
||||
contractPriv: econtractResp.contractPriv,
|
||||
}),
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPullCredit,
|
||||
wg.withdrawalGroupId,
|
||||
),
|
||||
|
@ -56,7 +56,7 @@ import {
|
||||
OperationAttemptResult,
|
||||
OperationAttemptResultType,
|
||||
} from "../util/retries.js";
|
||||
import { makeCoinAvailable, makeEventId } from "./common.js";
|
||||
import { makeCoinAvailable, makeTransactionId } from "./common.js";
|
||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||
import {
|
||||
getCandidateWithdrawalDenoms,
|
||||
@ -366,6 +366,6 @@ export async function acceptTip(
|
||||
await processTip(ws, tipId);
|
||||
}
|
||||
return {
|
||||
transactionId: makeEventId(TransactionType.Tip, tipId),
|
||||
transactionId: makeTransactionId(TransactionType.Tip, tipId),
|
||||
};
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ import {
|
||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||
import { checkDbInvariant } from "../util/invariants.js";
|
||||
import { RetryTags } from "../util/retries.js";
|
||||
import { makeEventId, TombstoneTag } from "./common.js";
|
||||
import { makeTombstoneId, makeTransactionId, TombstoneTag } from "./common.js";
|
||||
import { processDepositGroup } from "./deposits.js";
|
||||
import { getExchangeDetails } from "./exchanges.js";
|
||||
import {
|
||||
@ -193,7 +193,7 @@ export async function getTransactionById(
|
||||
const filteredRefunds = await Promise.all(
|
||||
Object.values(purchase.refunds).map(async (r) => {
|
||||
const t = await tx.tombstones.get(
|
||||
makeEventId(
|
||||
makeTombstoneId(
|
||||
TombstoneTag.DeleteRefund,
|
||||
purchase.proposalId,
|
||||
`${r.executionTime.t_s}`,
|
||||
@ -271,7 +271,7 @@ export async function getTransactionById(
|
||||
if (!theRefund) throw Error("not found");
|
||||
|
||||
const t = await tx.tombstones.get(
|
||||
makeEventId(
|
||||
makeTombstoneId(
|
||||
TombstoneTag.DeleteRefund,
|
||||
purchase.proposalId,
|
||||
executionTimeStr,
|
||||
@ -338,7 +338,10 @@ function buildTransactionForPushPaymentDebit(
|
||||
exchangeBaseUrl: pi.exchangeBaseUrl,
|
||||
contractPriv: pi.contractPriv,
|
||||
}),
|
||||
transactionId: makeEventId(TransactionType.PeerPushDebit, pi.pursePub),
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPushDebit,
|
||||
pi.pursePub,
|
||||
),
|
||||
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||
};
|
||||
}
|
||||
@ -359,7 +362,7 @@ function buildTransactionForPullPaymentDebit(
|
||||
summary: pi.contractTerms.summary,
|
||||
},
|
||||
timestamp: pi.timestampCreated,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPullDebit,
|
||||
pi.peerPullPaymentIncomingId,
|
||||
),
|
||||
@ -388,7 +391,7 @@ function buildTransactionForPullPaymentCredit(
|
||||
exchangeBaseUrl: wsr.exchangeBaseUrl,
|
||||
contractPriv: wsr.wgInfo.contractPriv,
|
||||
}),
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPullCredit,
|
||||
wsr.withdrawalGroupId,
|
||||
),
|
||||
@ -414,7 +417,7 @@ function buildTransactionForPushPaymentCredit(
|
||||
},
|
||||
pending: !wsr.timestampFinish,
|
||||
timestamp: wsr.timestampStart,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.PeerPushCredit,
|
||||
wsr.withdrawalGroupId,
|
||||
),
|
||||
@ -443,7 +446,7 @@ function buildTransactionForBankIntegratedWithdraw(
|
||||
exchangeBaseUrl: wsr.exchangeBaseUrl,
|
||||
pending: !wsr.timestampFinish,
|
||||
timestamp: wsr.timestampStart,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Withdrawal,
|
||||
wsr.withdrawalGroupId,
|
||||
),
|
||||
@ -483,7 +486,7 @@ function buildTransactionForManualWithdraw(
|
||||
exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl,
|
||||
pending: !withdrawalGroup.timestampFinish,
|
||||
timestamp: withdrawalGroup.timestampStart,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Withdrawal,
|
||||
withdrawalGroup.withdrawalGroupId,
|
||||
),
|
||||
@ -504,7 +507,10 @@ function buildTransactionForDeposit(
|
||||
frozen: false,
|
||||
timestamp: dg.timestampCreated,
|
||||
targetPaytoUri: dg.wire.payto_uri,
|
||||
transactionId: makeEventId(TransactionType.Deposit, dg.depositGroupId),
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Deposit,
|
||||
dg.depositGroupId,
|
||||
),
|
||||
depositGroupId: dg.depositGroupId,
|
||||
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||
};
|
||||
@ -523,7 +529,10 @@ function buildTransactionForTip(
|
||||
pending: !tipRecord.pickedUpTimestamp,
|
||||
frozen: false,
|
||||
timestamp: tipRecord.acceptedTimestamp,
|
||||
transactionId: makeEventId(TransactionType.Tip, tipRecord.walletTipId),
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Tip,
|
||||
tipRecord.walletTipId,
|
||||
),
|
||||
merchantBaseUrl: tipRecord.merchantBaseUrl,
|
||||
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||
};
|
||||
@ -606,11 +615,11 @@ async function buildTransactionForRefund(
|
||||
return {
|
||||
type: TransactionType.Refund,
|
||||
info,
|
||||
refundedTransactionId: makeEventId(
|
||||
refundedTransactionId: makeTransactionId(
|
||||
TransactionType.Payment,
|
||||
purchaseRecord.proposalId,
|
||||
),
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Refund,
|
||||
purchaseRecord.proposalId,
|
||||
`${refundInfo.executionTime.t_s}`,
|
||||
@ -667,7 +676,7 @@ async function buildTransactionForPurchase(
|
||||
amountEffective: Amounts.stringify(r.amountAppliedEffective),
|
||||
amountRaw: Amounts.stringify(r.amountAppliedRaw),
|
||||
timestamp: r.executionTime,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Refund,
|
||||
purchaseRecord.proposalId,
|
||||
`${r.executionTime.t_s}`,
|
||||
@ -694,7 +703,7 @@ async function buildTransactionForPurchase(
|
||||
pending: purchaseRecord.purchaseStatus === PurchaseStatus.Paying,
|
||||
refunds,
|
||||
timestamp,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Payment,
|
||||
purchaseRecord.proposalId,
|
||||
),
|
||||
@ -854,7 +863,7 @@ export async function getTransactions(
|
||||
const filteredRefunds = await Promise.all(
|
||||
Object.values(purchase.refunds).map(async (r) => {
|
||||
const t = await tx.tombstones.get(
|
||||
makeEventId(
|
||||
makeTombstoneId(
|
||||
TombstoneTag.DeleteRefund,
|
||||
purchase.proposalId,
|
||||
`${r.executionTime.t_s}`,
|
||||
@ -1077,7 +1086,7 @@ export async function deleteTransaction(
|
||||
// This should just influence the history view,
|
||||
// but won't delete any actual refund information.
|
||||
await tx.tombstones.put({
|
||||
id: makeEventId(
|
||||
id: makeTombstoneId(
|
||||
TombstoneTag.DeleteRefund,
|
||||
proposalId,
|
||||
executionTimeStr,
|
||||
@ -1096,7 +1105,7 @@ export async function deleteTransaction(
|
||||
if (debit) {
|
||||
await tx.peerPullPaymentIncoming.delete(peerPullPaymentIncomingId);
|
||||
await tx.tombstones.put({
|
||||
id: makeEventId(
|
||||
id: makeTombstoneId(
|
||||
TombstoneTag.DeletePeerPullDebit,
|
||||
peerPullPaymentIncomingId,
|
||||
),
|
||||
@ -1112,7 +1121,7 @@ export async function deleteTransaction(
|
||||
if (debit) {
|
||||
await tx.peerPushPaymentInitiations.delete(pursePub);
|
||||
await tx.tombstones.put({
|
||||
id: makeEventId(TombstoneTag.DeletePeerPushDebit, pursePub),
|
||||
id: makeTombstoneId(TombstoneTag.DeletePeerPushDebit, pursePub),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ import {
|
||||
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||
} from "../versions.js";
|
||||
import {
|
||||
makeEventId,
|
||||
makeTransactionId,
|
||||
storeOperationError,
|
||||
storeOperationPending,
|
||||
} from "./common.js";
|
||||
@ -1797,7 +1797,7 @@ export async function acceptWithdrawalFromUri(
|
||||
return {
|
||||
reservePub: existingWithdrawalGroup.reservePub,
|
||||
confirmTransferUrl: url,
|
||||
transactionId: makeEventId(
|
||||
transactionId: makeTransactionId(
|
||||
TransactionType.Withdrawal,
|
||||
existingWithdrawalGroup.withdrawalGroupId,
|
||||
),
|
||||
@ -1858,7 +1858,7 @@ export async function acceptWithdrawalFromUri(
|
||||
return {
|
||||
reservePub: withdrawalGroup.reservePub,
|
||||
confirmTransferUrl: withdrawInfo.confirmTransferUrl,
|
||||
transactionId: makeEventId(TransactionType.Withdrawal, withdrawalGroupId),
|
||||
transactionId: makeTransactionId(TransactionType.Withdrawal, withdrawalGroupId),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1919,6 +1919,6 @@ export async function createManualWithdrawal(
|
||||
return {
|
||||
reservePub: withdrawalGroup.reservePub,
|
||||
exchangePaytoUris: exchangePaytoUris,
|
||||
transactionId: makeEventId(TransactionType.Withdrawal, withdrawalGroupId),
|
||||
transactionId: makeTransactionId(TransactionType.Withdrawal, withdrawalGroupId),
|
||||
};
|
||||
}
|
||||
|
@ -60,7 +60,9 @@ const commonTransaction = {
|
||||
amountEffective: "KUDOS:9.2",
|
||||
pending: false,
|
||||
timestamp: TalerProtocolTimestamp.now(),
|
||||
transactionId: "12",
|
||||
transactionId: "txn:deposit:12",
|
||||
frozen: false,
|
||||
type: TransactionType.Deposit,
|
||||
} as TransactionCommon;
|
||||
|
||||
import merchantIcon from "../../static-dev/merchant-icon.jpeg";
|
||||
|
Loading…
Reference in New Issue
Block a user