aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-10-09 02:23:06 +0200
committerFlorian Dold <florian@dold.me>2022-10-09 02:23:06 +0200
commit19f3e6321d68adbaf9e8ca2d03efac6706d3fdea (patch)
treed5b5999de159db9ccf6496c61a92e51323c4e51c
parent8ac5080607d28f8dcd84a949221a551a3f66cea8 (diff)
wallet-core: put contract terms into separate object store
-rw-r--r--packages/taler-util/src/backupTypes.ts2
-rw-r--r--packages/taler-wallet-core/src/db.ts47
-rw-r--r--packages/taler-wallet-core/src/operations/backup/export.ts17
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts47
-rw-r--r--packages/taler-wallet-core/src/operations/pay-merchant.ts102
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts78
6 files changed, 183 insertions, 110 deletions
diff --git a/packages/taler-util/src/backupTypes.ts b/packages/taler-util/src/backupTypes.ts
index 777086599..620f476ad 100644
--- a/packages/taler-util/src/backupTypes.ts
+++ b/packages/taler-util/src/backupTypes.ts
@@ -909,6 +909,8 @@ export interface BackupPurchase {
/**
* Signature on the contract terms.
+ *
+ * FIXME: Better name needed.
*/
merchant_sig?: string;
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index b019be67a..ec11f4d47 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1085,18 +1085,16 @@ export enum PurchaseStatus {
Paid = OperationStatusRange.DORMANT_START + 5,
}
+/**
+ * Partial information about the downloaded proposal.
+ * Only contains data that is relevant for indexing on the
+ * "purchases" object stores.
+ */
export interface ProposalDownload {
- /**
- * The contract that was offered by the merchant.
- */
- contractTermsRaw: any;
-
- /**
- * Extracted / parsed data from the contract terms.
- *
- * FIXME: Do we need to store *all* that data in duplicate?
- */
- contractData: WalletContractData;
+ contractTermsHash: string;
+ fulfillmentUrl?: string;
+ currency: string;
+ contractTermsMerchantSig: string;
}
export interface PurchasePayInfo {
@@ -1723,6 +1721,7 @@ export interface PeerPullPaymentInitiationRecord {
* Contract terms for the other party.
*
* FIXME: Nail down type!
+ * FIXME: Put in contractTerms store
*/
contractTerms: any;
}
@@ -1819,6 +1818,18 @@ export interface CoinAvailabilityRecord {
freshCoinCount: number;
}
+export interface ContractTermsRecord {
+ /**
+ * Contract terms hash.
+ */
+ h: string;
+
+ /**
+ * Contract terms JSON.
+ */
+ contractTermsRaw: any;
+}
+
/**
* Schema definition for the IndexedDB
* wallet database.
@@ -1937,13 +1948,8 @@ export const WalletStoresV1 = {
byStatus: describeIndex("byStatus", "purchaseStatus"),
byFulfillmentUrl: describeIndex(
"byFulfillmentUrl",
- "download.contractData.fulfillmentUrl",
+ "download.fulfillmentUrl",
),
- // FIXME: Deduplicate!
- byMerchantUrlAndOrderId: describeIndex("byMerchantUrlAndOrderId", [
- "download.contractData.merchantBaseUrl",
- "download.contractData.orderId",
- ]),
byUrlAndOrderId: describeIndex("byUrlAndOrderId", [
"merchantBaseUrl",
"orderId",
@@ -2088,6 +2094,13 @@ export const WalletStoresV1 = {
}),
{},
),
+ contractTerms: describeStore(
+ "contractTerms",
+ describeContents<ContractTermsRecord>({
+ keyPath: "h",
+ }),
+ {},
+ ),
};
/**
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts
index d16b344f6..2e2a1c4b4 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -88,6 +88,7 @@ export async function exportBackup(
x.exchanges,
x.exchangeDetails,
x.coins,
+ x.contractTerms,
x.denominations,
x.purchases,
x.refreshGroups,
@@ -353,7 +354,7 @@ export async function exportBackup(
const purchaseProposalIdSet = new Set<string>();
- await tx.purchases.iter().forEach((purch) => {
+ await tx.purchases.iter().forEachAsync(async (purch) => {
const refunds: BackupRefundItem[] = [];
purchaseProposalIdSet.add(purch.proposalId);
for (const refundKey of Object.keys(purch.refunds)) {
@@ -418,8 +419,18 @@ export async function exportBackup(
};
}
+ let contractTermsRaw = undefined;
+ if (purch.download) {
+ const contractTermsRecord = await tx.contractTerms.get(
+ purch.download.contractTermsHash,
+ );
+ if (contractTermsRecord) {
+ contractTermsRaw = contractTermsRecord.contractTermsRaw;
+ }
+ }
+
backupPurchases.push({
- contract_terms_raw: purch.download?.contractTermsRaw,
+ contract_terms_raw: contractTermsRaw,
auto_refund_deadline: purch.autoRefundDeadline,
merchant_pay_sig: purch.merchantPaySig,
pay_info: backupPayInfo,
@@ -428,7 +439,7 @@ export async function exportBackup(
timestamp_accepted: purch.timestampAccept,
timestamp_first_successful_pay: purch.timestampFirstSuccessfulPay,
nonce_priv: purch.noncePriv,
- merchant_sig: purch.download?.contractData.merchantSig,
+ merchant_sig: purch.download?.contractTermsMerchantSig,
claim_token: purch.claimToken,
merchant_base_url: purch.merchantBaseUrl,
order_id: purch.orderId,
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index bb5fe56e2..3ee3680fe 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -64,6 +64,7 @@ import { checkLogicInvariant } from "../../util/invariants.js";
import { GetReadOnlyAccess, GetReadWriteAccess } from "../../util/query.js";
import { makeCoinAvailable, makeEventId, TombstoneTag } from "../common.js";
import { getExchangeDetails } from "../exchanges.js";
+import { extractContractData } from "../pay-merchant.js";
import { provideBackupState } from "./state.js";
const logger = new Logger("operations/backup/import.ts");
@@ -630,49 +631,25 @@ export async function importBackup(
maxWireFee = Amounts.getZero(amount.currency);
}
const download: ProposalDownload = {
- contractData: {
- amount,
- contractTermsHash: contractTermsHash,
- fulfillmentUrl: parsedContractTerms.fulfillment_url ?? "",
- merchantBaseUrl: parsedContractTerms.merchant_base_url,
- merchantPub: parsedContractTerms.merchant_pub,
- merchantSig: backupPurchase.merchant_sig!,
- orderId: parsedContractTerms.order_id,
- summary: parsedContractTerms.summary,
- autoRefund: parsedContractTerms.auto_refund,
- maxWireFee,
- payDeadline: parsedContractTerms.pay_deadline,
- refundDeadline: parsedContractTerms.refund_deadline,
- wireFeeAmortization:
- parsedContractTerms.wire_fee_amortization || 1,
- allowedAuditors: parsedContractTerms.auditors.map((x) => ({
- auditorBaseUrl: x.url,
- auditorPub: x.auditor_pub,
- })),
- allowedExchanges: parsedContractTerms.exchanges.map((x) => ({
- exchangeBaseUrl: x.url,
- exchangePub: x.master_pub,
- })),
- timestamp: parsedContractTerms.timestamp,
- wireMethod: parsedContractTerms.wire_method,
- wireInfoHash: parsedContractTerms.h_wire,
- maxDepositFee: Amounts.parseOrThrow(parsedContractTerms.max_fee),
- merchant: parsedContractTerms.merchant,
- products: parsedContractTerms.products,
- summaryI18n: parsedContractTerms.summary_i18n,
- deliveryDate: parsedContractTerms.delivery_date,
- deliveryLocation: parsedContractTerms.delivery_location,
- },
- contractTermsRaw: backupPurchase.contract_terms_raw,
+ contractTermsHash,
+ contractTermsMerchantSig: backupPurchase.merchant_sig!,
+ currency: amount.currency,
+ fulfillmentUrl: backupPurchase.contract_terms_raw.fulfillment_url,
};
+ const contractData = extractContractData(
+ backupPurchase.contract_terms_raw,
+ contractTermsHash,
+ download.contractTermsMerchantSig,
+ );
+
let payInfo: PurchasePayInfo | undefined = undefined;
if (backupPurchase.pay_info) {
payInfo = {
coinDepositPermissions: undefined,
payCoinSelection: await recoverPayCoinSelection(
tx,
- download.contractData,
+ contractData,
backupPurchase.pay_info,
),
payCoinSelectionUid: backupPurchase.pay_info.pay_coins_uid,
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index d590177c2..e805c0ea1 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -115,6 +115,7 @@ import {
throwUnexpectedRequestError,
} from "../util/http.js";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
+import { GetReadOnlyAccess } from "../util/query.js";
import {
OperationAttemptResult,
OperationAttemptResultType,
@@ -256,12 +257,34 @@ function getPayRequestTimeout(purchase: PurchaseRecord): Duration {
* (Async since in the future this will query the DB.)
*/
export async function expectProposalDownload(
+ ws: InternalWalletState,
p: PurchaseRecord,
-): Promise<ProposalDownload> {
+): Promise<{
+ contractData: WalletContractData;
+ contractTermsRaw: any;
+}> {
if (!p.download) {
throw Error("expected proposal to be downloaded");
}
- return p.download;
+ const download = p.download;
+ return await ws.db
+ .mktx((x) => [x.contractTerms])
+ .runReadOnly(async (tx) => {
+ const contractTerms = await tx.contractTerms.get(
+ download.contractTermsHash,
+ );
+ if (!contractTerms) {
+ throw Error("contract terms not found");
+ }
+ return {
+ contractData: extractContractData(
+ contractTerms.contractTermsRaw,
+ download.contractTermsHash,
+ download.contractTermsMerchantSig,
+ ),
+ contractTermsRaw: contractTerms.contractTermsRaw,
+ };
+ });
}
export function extractContractData(
@@ -494,7 +517,7 @@ export async function processDownloadProposal(
logger.trace(`extracted contract data: ${j2s(contractData)}`);
await ws.db
- .mktx((x) => [x.purchases])
+ .mktx((x) => [x.purchases, x.contractTerms])
.runReadWrite(async (tx) => {
const p = await tx.purchases.get(proposalId);
if (!p) {
@@ -504,9 +527,15 @@ export async function processDownloadProposal(
return;
}
p.download = {
- contractData,
- contractTermsRaw: proposalResp.contract_terms,
+ contractTermsHash,
+ contractTermsMerchantSig: contractData.merchantSig,
+ currency: contractData.amount.currency,
+ fulfillmentUrl: contractData.fulfillmentUrl,
};
+ await tx.contractTerms.put({
+ h: contractTermsHash,
+ contractTermsRaw: proposalResp.contract_terms,
+ });
if (
fulfillmentUrl &&
(fulfillmentUrl.startsWith("http://") ||
@@ -636,7 +665,7 @@ async function storeFirstPaySuccess(
): Promise<void> {
const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
await ws.db
- .mktx((x) => [x.purchases])
+ .mktx((x) => [x.purchases, x.contractTerms])
.runReadWrite(async (tx) => {
const purchase = await tx.purchases.get(proposalId);
@@ -655,7 +684,18 @@ async function storeFirstPaySuccess(
purchase.timestampFirstSuccessfulPay = now;
purchase.lastSessionId = sessionId;
purchase.merchantPaySig = paySig;
- const protoAr = purchase.download!.contractData.autoRefund;
+ const dl = purchase.download;
+ checkDbInvariant(!!dl);
+ const contractTermsRecord = await tx.contractTerms.get(
+ dl.contractTermsHash,
+ );
+ checkDbInvariant(!!contractTermsRecord);
+ const contractData = extractContractData(
+ contractTermsRecord.contractTermsRaw,
+ dl.contractTermsHash,
+ dl.contractTermsMerchantSig,
+ );
+ const protoAr = contractData.autoRefund;
if (protoAr) {
const ar = Duration.fromTalerProtocolDuration(protoAr);
logger.info("auto_refund present");
@@ -739,7 +779,7 @@ async function handleInsufficientFunds(
throw new TalerProtocolViolationError();
}
- const { contractData } = proposal.download!;
+ const { contractData } = await expectProposalDownload(ws, proposal);
const prevPayCoins: PreviousPayCoins = [];
@@ -1254,11 +1294,7 @@ export async function checkPaymentByProposalId(
throw Error("existing proposal is in wrong state");
}
}
- const d = proposal.download;
- if (!d) {
- logger.error("bad proposal", proposal);
- throw Error("proposal is in invalid state");
- }
+ const d = await expectProposalDownload(ws, proposal);
const contractData = d.contractData;
const merchantSig = d.contractData.merchantSig;
if (!merchantSig) {
@@ -1338,7 +1374,7 @@ export async function checkPaymentByProposalId(
// FIXME: This does not surface the original error
throw Error("submitting pay failed");
}
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1349,7 +1385,7 @@ export async function checkPaymentByProposalId(
proposalId,
};
} else if (!purchase.timestampFirstSuccessfulPay) {
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1364,7 +1400,7 @@ export async function checkPaymentByProposalId(
purchase.purchaseStatus === PurchaseStatus.Paid ||
purchase.purchaseStatus === PurchaseStatus.QueryingRefund ||
purchase.purchaseStatus === PurchaseStatus.QueryingAutoRefund;
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
return {
status: PreparePayResultType.AlreadyConfirmed,
contractTerms: download.contractTermsRaw,
@@ -1392,11 +1428,9 @@ export async function getContractTermsDetails(
throw Error(`proposal with id ${proposalId} not found`);
}
- if (!proposal.download || !proposal.download.contractData) {
- throw Error("proposal is in invalid state");
- }
+ const d = await expectProposalDownload(ws, proposal);
- return proposal.download.contractData;
+ return d.contractData;
}
/**
@@ -1516,12 +1550,13 @@ export async function runPayForConfirmPay(
.runReadOnly(async (tx) => {
return tx.purchases.get(proposalId);
});
- if (!purchase?.download) {
+ if (!purchase) {
throw Error("purchase record not available anymore");
}
+ const d = await expectProposalDownload(ws, purchase);
return {
type: ConfirmPayResultType.Done,
- contractTerms: purchase.download.contractTermsRaw,
+ contractTerms: d.contractTermsRaw,
transactionId: makeEventId(TransactionType.Payment, proposalId),
};
}
@@ -1599,7 +1634,7 @@ export async function confirmPay(
throw Error(`proposal with id ${proposalId} not found`);
}
- const d = proposal.download;
+ const d = await expectProposalDownload(ws, proposal);
if (!d) {
throw Error("proposal is in invalid state");
}
@@ -1810,7 +1845,7 @@ export async function processPurchasePay(
const payInfo = purchase.payInfo;
checkDbInvariant(!!payInfo, "payInfo");
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
if (!purchase.merchantPaySig) {
const payUrl = new URL(
`orders/${download.contractData.orderId}/pay`,
@@ -2007,7 +2042,7 @@ export async function prepareRefund(
const purchase = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
- return tx.purchases.indexes.byMerchantUrlAndOrderId.get([
+ return tx.purchases.indexes.byUrlAndOrderId.get([
parseResult.merchantBaseUrl,
parseResult.orderId,
]);
@@ -2020,10 +2055,10 @@ export async function prepareRefund(
}
const awaiting = await queryAndSaveAwaitingRefund(ws, purchase);
- const summary = await calculateRefundSummary(purchase);
+ const summary = await calculateRefundSummary(ws, purchase);
const proposalId = purchase.proposalId;
- const { contractData: c } = await expectProposalDownload(purchase);
+ const { contractData: c } = await expectProposalDownload(ws, purchase);
return {
proposalId,
@@ -2380,9 +2415,10 @@ async function acceptRefunds(
}
async function calculateRefundSummary(
+ ws: InternalWalletState,
p: PurchaseRecord,
): Promise<RefundSummary> {
- const download = await expectProposalDownload(p);
+ const download = await expectProposalDownload(ws, p);
let amountRefundGranted = Amounts.getZero(
download.contractData.amount.currency,
);
@@ -2456,7 +2492,7 @@ export async function applyRefund(
const purchase = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
- return tx.purchases.indexes.byMerchantUrlAndOrderId.get([
+ return tx.purchases.indexes.byUrlAndOrderId.get([
parseResult.merchantBaseUrl,
parseResult.orderId,
]);
@@ -2513,8 +2549,8 @@ export async function applyRefundFromPurchaseId(
throw Error("purchase no longer exists");
}
- const summary = await calculateRefundSummary(purchase);
- const download = await expectProposalDownload(purchase);
+ const summary = await calculateRefundSummary(ws, purchase);
+ const download = await expectProposalDownload(ws, purchase);
return {
contractTermsHash: download.contractData.contractTermsHash,
@@ -2542,7 +2578,7 @@ async function queryAndSaveAwaitingRefund(
purchase: PurchaseRecord,
waitForAutoRefund?: boolean,
): Promise<AmountJson> {
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
const requestUrl = new URL(
`orders/${download.contractData.orderId}`,
download.contractData.merchantBaseUrl,
@@ -2621,7 +2657,7 @@ export async function processPurchaseQueryRefund(
return OperationAttemptResult.finishedEmpty();
}
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
if (purchase.timestampFirstSuccessfulPay) {
if (
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index d8069436a..6955d7b17 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -48,6 +48,7 @@ import {
WalletRefundItem,
WithdrawalGroupRecord,
WithdrawalRecordType,
+ WalletContractData,
} from "../db.js";
import { InternalWalletState } from "../internal-wallet-state.js";
import { checkDbInvariant } from "../util/invariants.js";
@@ -55,7 +56,11 @@ import { RetryTags } from "../util/retries.js";
import { makeEventId, TombstoneTag } from "./common.js";
import { processDepositGroup } from "./deposits.js";
import { getExchangeDetails } from "./exchanges.js";
-import { expectProposalDownload, processPurchasePay } from "./pay-merchant.js";
+import {
+ expectProposalDownload,
+ extractContractData,
+ processPurchasePay,
+} from "./pay-merchant.js";
import { processRefreshGroup } from "./refresh.js";
import { processTip } from "./tip.js";
import {
@@ -199,7 +204,7 @@ export async function getTransactionById(
}),
);
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
const cleanRefunds = filteredRefunds.filter(
(x): x is WalletRefundItem => !!x,
@@ -214,7 +219,12 @@ export async function getTransactionById(
const payOpId = RetryTags.forPay(purchase);
const payRetryRecord = await tx.operationRetries.get(payOpId);
- return buildTransactionForPurchase(purchase, refunds, payRetryRecord);
+ return buildTransactionForPurchase(
+ purchase,
+ contractData,
+ refunds,
+ payRetryRecord,
+ );
});
} else if (type === TransactionType.Refresh) {
const refreshGroupId = rest[0];
@@ -268,14 +278,19 @@ export async function getTransactionById(
),
);
if (t) throw Error("deleted");
- const download = await expectProposalDownload(purchase);
+ const download = await expectProposalDownload(ws, purchase);
const contractData = download.contractData;
const refunds = mergeRefundByExecutionTime(
[theRefund],
Amounts.getZero(contractData.amount.currency),
);
- return buildTransactionForRefund(purchase, refunds[0], undefined);
+ return buildTransactionForRefund(
+ purchase,
+ contractData,
+ refunds[0],
+ undefined,
+ );
});
} else if (type === TransactionType.PeerPullDebit) {
const peerPullPaymentIncomingId = rest[0];
@@ -572,12 +587,10 @@ function mergeRefundByExecutionTime(
async function buildTransactionForRefund(
purchaseRecord: PurchaseRecord,
+ contractData: WalletContractData,
refundInfo: MergedRefundInfo,
ort?: OperationRetryRecord,
): Promise<Transaction> {
- const download = await expectProposalDownload(purchaseRecord);
- const contractData = download.contractData;
-
const info: OrderShortInfo = {
merchant: contractData.merchant,
orderId: contractData.orderId,
@@ -617,11 +630,10 @@ async function buildTransactionForRefund(
async function buildTransactionForPurchase(
purchaseRecord: PurchaseRecord,
+ contractData: WalletContractData,
refundsInfo: MergedRefundInfo[],
ort?: OperationRetryRecord,
): Promise<Transaction> {
- const download = await expectProposalDownload(purchaseRecord);
- const contractData = download.contractData;
const zero = Amounts.getZero(contractData.amount.currency);
const info: OrderShortInfo = {
@@ -689,7 +701,8 @@ async function buildTransactionForPurchase(
proposalId: purchaseRecord.proposalId,
info,
frozen:
- purchaseRecord.purchaseStatus === PurchaseStatus.PaymentAbortFinished ?? false,
+ purchaseRecord.purchaseStatus === PurchaseStatus.PaymentAbortFinished ??
+ false,
...(ort?.lastError ? { error: ort.lastError } : {}),
};
}
@@ -715,6 +728,7 @@ export async function getTransactions(
x.peerPushPaymentInitiations,
x.planchets,
x.purchases,
+ x.contractTerms,
x.recoupGroups,
x.tips,
x.tombstones,
@@ -814,19 +828,29 @@ export async function getTransactions(
if (!purchase.payInfo) {
return;
}
- if (
- shouldSkipCurrency(
- transactionsRequest,
- download.contractData.amount.currency,
- )
- ) {
+ if (shouldSkipCurrency(transactionsRequest, download.currency)) {
return;
}
- const contractData = download.contractData;
- if (shouldSkipSearch(transactionsRequest, [contractData.summary])) {
+ const contractTermsRecord = await tx.contractTerms.get(
+ download.contractTermsHash,
+ );
+ if (!contractTermsRecord) {
+ return;
+ }
+ if (
+ shouldSkipSearch(transactionsRequest, [
+ contractTermsRecord?.contractTermsRaw?.summary || "",
+ ])
+ ) {
return;
}
+ const contractData = extractContractData(
+ contractTermsRecord?.contractTermsRaw,
+ download.contractTermsHash,
+ download.contractTermsMerchantSig,
+ );
+
const filteredRefunds = await Promise.all(
Object.values(purchase.refunds).map(async (r) => {
const t = await tx.tombstones.get(
@@ -847,19 +871,29 @@ export async function getTransactions(
const refunds = mergeRefundByExecutionTime(
cleanRefunds,
- Amounts.getZero(contractData.amount.currency),
+ Amounts.getZero(download.currency),
);
refunds.forEach(async (refundInfo) => {
transactions.push(
- await buildTransactionForRefund(purchase, refundInfo, undefined),
+ await buildTransactionForRefund(
+ purchase,
+ contractData,
+ refundInfo,
+ undefined,
+ ),
);
});
const payOpId = RetryTags.forPay(purchase);
const payRetryRecord = await tx.operationRetries.get(payOpId);
transactions.push(
- await buildTransactionForPurchase(purchase, refunds, payRetryRecord),
+ await buildTransactionForPurchase(
+ purchase,
+ contractData,
+ refunds,
+ payRetryRecord,
+ ),
);
});