commit 1f83b0afa73d26ffb2f61ec466032f14f6d07ab3
parent f1b329b668e0795726f0fa672b5b91fcc6986df6
Author: Florian Dold <florian@dold.me>
Date: Sun, 24 Aug 2025 19:18:45 +0200
wallet-core: refactor
Diffstat:
1 file changed, 293 insertions(+), 285 deletions(-)
diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts
@@ -30,6 +30,7 @@ import {
Amounts,
ContractTermsUtil,
DenomLossEventType,
+ DevExperimentUri,
Duration,
Logger,
MerchantContractTermsV0,
@@ -218,291 +219,7 @@ export async function applyDevExperiment(
return;
}
case "add-fake-tx": {
- const txType = parsedUri.query?.get("txType") ?? "withdrawal";
- const withdrawalGroupId = encodeCrock(getRandomBytes(32));
- const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
- switch (txType) {
- case "withdrawal": {
- const secretSeed = encodeCrock(getRandomBytes(32));
- const reservePair = await wex.ws.cryptoApi.createEddsaKeypair({});
- const exchangeBaseUrl =
- parsedUri.query?.get("exchangeBaseUrl") ??
- "https://exchange.demo.taler.net/";
- const trelStr = parsedUri.query?.get("tRel") ?? undefined;
- const amountEffectiveStr = parsedUri.query?.get("amountEffective");
- if (!amountEffectiveStr) {
- throw Error("missing amountEffective option");
- }
- const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
- let timestamp: AbsoluteTime;
- if (trelStr) {
- timestamp = AbsoluteTime.subtractDuraction(
- AbsoluteTime.now(),
- Duration.fromPrettyString(trelStr),
- );
- } else {
- timestamp = AbsoluteTime.now();
- }
- await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
- await tx.withdrawalGroups.add({
- denomSelUid: encodeCrock(getRandomBytes(32)),
- reservePriv: reservePair.priv,
- reservePub: reservePair.pub,
- secretSeed,
- status: WithdrawalGroupStatus.Done,
- timestampStart: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- timestampFinish: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- withdrawalGroupId,
- wgInfo: {
- withdrawalType: WithdrawalRecordType.BankManual,
- exchangeCreditAccounts: [
- {
- paytoUri: "payto://x-taler-bank/test/test",
- status: "ok",
- },
- ],
- },
- denomsSel: {
- totalCoinValue: Amounts.stringify(amountEffective),
- hasDenomWithAgeRestriction: false,
- totalWithdrawCost: Amounts.stringify(amountEffective),
- selectedDenoms: [],
- },
- exchangeBaseUrl,
- instructedAmount: Amounts.stringify(amountEffective),
- effectiveWithdrawalAmount: Amounts.stringify(amountEffective),
- rawWithdrawalAmount: Amounts.stringify(amountEffective),
- });
- await ctx.updateTransactionMeta(tx);
- });
- break;
- }
- case "payment": {
- const proposalId = encodeCrock(getRandomBytes(32));
- const ctx = new PayMerchantTransactionContext(wex, proposalId);
- const summary = parsedUri.query?.get("summary") ?? "Test";
- const amountEffectiveStr = parsedUri.query?.get("amountEffective");
- if (!amountEffectiveStr) {
- throw Error("missing amountEffective option");
- }
- const merchantName =
- parsedUri.query?.get("merchantName") ?? "Test Merchant";
- const exchangeBaseUrl =
- parsedUri.query?.get("exchangeBaseUrl") ??
- "https://exchange.demo.taler.net/";
- const merchantBaseUrl =
- parsedUri.query?.get("merchantBaseUrl") ??
- "https://backend.demo.taler.net/";
- const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
- const trelStr = parsedUri.query?.get("tRel") ?? undefined;
- let timestamp: AbsoluteTime;
- if (trelStr) {
- timestamp = AbsoluteTime.subtractDuraction(
- AbsoluteTime.now(),
- Duration.fromPrettyString(trelStr),
- );
- } else {
- timestamp = AbsoluteTime.now();
- }
- const orderId = encodeCrock(getRandomBytes(8));
- const noncePair = await wex.ws.cryptoApi.createEddsaKeypair({});
- const merchantPub = encodeCrock(getRandomBytes(32));
- const ct: MerchantContractTermsV0 = {
- amount: Amounts.stringify(amountEffective),
- exchanges: [
- {
- master_pub: encodeCrock(getRandomBytes(32)),
- priority: 1,
- url: exchangeBaseUrl,
- },
- ],
- h_wire: encodeCrock(getRandomBytes(64)),
- max_fee: Amounts.stringify(Amounts.zeroOfAmount(amountEffective)),
- timestamp: AbsoluteTime.toProtocolTimestamp(timestamp),
- summary,
- order_id: orderId,
- merchant_base_url: merchantBaseUrl,
- merchant_pub: merchantPub,
- wire_method: "x-taler-bank",
- version: MerchantContractVersion.V0,
- nonce: encodeCrock(getRandomBytes(32)),
- merchant: {
- name: merchantName,
- },
- pay_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
- refund_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
- wire_transfer_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
- };
- const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
- await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
- await tx.contractTerms.put({
- contractTermsRaw: ct,
- h: contractTermsHash,
- });
- await tx.purchases.put({
- autoRefundDeadline: undefined,
- claimToken: encodeCrock(getRandomBytes(32)),
- downloadSessionId: encodeCrock(getRandomBytes(32)),
- orderId,
- proposalId,
- download: {
- contractTermsHash,
- contractTermsMerchantSig: encodeCrock(getRandomBytes(64)),
- currency: Amounts.currencyOf(amountEffective),
- },
- merchantBaseUrl,
- purchaseStatus: PurchaseStatus.Done,
- repurchaseProposalId: undefined,
- lastSessionId: undefined,
- merchantPaySig: encodeCrock(getRandomBytes(64)),
- noncePriv: noncePair.priv,
- noncePub: noncePair.pub,
- payInfo: {
- totalPayCost: Amounts.stringify(amountEffective),
- },
- posConfirmation: undefined,
- secretSeed: encodeCrock(getRandomBytes(32)),
- timestamp: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- shared: false,
- timestampFirstSuccessfulPay: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- timestampAccept: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- timestampLastRefundStatus: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- refundAmountAwaiting: undefined,
- });
- await ctx.updateTransactionMeta(tx);
- });
- break;
- }
- case "peer-push-debit": {
- const pursePair = await wex.cryptoApi.createEddsaKeypair({});
- const pursePub = pursePair.pub;
- const ctx = new PeerPushDebitTransactionContext(wex, pursePub);
- const summary = parsedUri.query?.get("summary") ?? "Test";
- const amountEffectiveStr = parsedUri.query?.get("amountEffective");
- if (!amountEffectiveStr) {
- throw Error("missing amountEffective option");
- }
- const exchangeBaseUrl =
- parsedUri.query?.get("exchangeBaseUrl") ??
- "https://exchange.demo.taler.net/";
- const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
- const trelStr = parsedUri.query?.get("tRel") ?? undefined;
- let timestamp: AbsoluteTime;
- if (trelStr) {
- timestamp = AbsoluteTime.subtractDuraction(
- AbsoluteTime.now(),
- Duration.fromPrettyString(trelStr),
- );
- } else {
- timestamp = AbsoluteTime.now();
- }
- const ct: PeerContractTerms = {
- amount: Amounts.stringify(amountEffective),
- purse_expiration: AbsoluteTime.toProtocolTimestamp(timestamp),
- summary,
- };
- const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
- const contractPair = await wex.cryptoApi.createEddsaKeypair({});
- const mergePair = await wex.cryptoApi.createEddsaKeypair({});
- await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
- await tx.contractTerms.put({
- contractTermsRaw: ct,
- h: contractTermsHash,
- });
- await tx.peerPushDebit.put({
- amount: Amounts.stringify(amountEffective),
- contractEncNonce: encodeCrock(getRandomBytes(32)),
- contractPriv: contractPair.priv,
- contractPub: contractPair.pub,
- contractTermsHash: contractTermsHash,
- exchangeBaseUrl,
- mergePriv: mergePair.priv,
- mergePub: mergePair.pub,
- purseExpiration: timestampProtocolToDb(ct.purse_expiration),
- pursePriv: pursePair.priv,
- pursePub: pursePair.pub,
- status: PeerPushDebitStatus.Done,
- timestampCreated: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- totalCost: Amounts.stringify(amountEffective),
- });
- await ctx.updateTransactionMeta(tx);
- });
- break;
- }
- case "peer-push-credit": {
- const pursePair = await wex.cryptoApi.createEddsaKeypair({});
- const pursePub = pursePair.pub;
- const peerPushCreditId = encodeCrock(getRandomBytes(32));
- const ctx = new PeerPushCreditTransactionContext(wex, pursePub);
- const summary = parsedUri.query?.get("summary") ?? "Test";
- const amountEffectiveStr = parsedUri.query?.get("amountEffective");
- if (!amountEffectiveStr) {
- throw Error("missing amountEffective option");
- }
- const exchangeBaseUrl =
- parsedUri.query?.get("exchangeBaseUrl") ??
- "https://exchange.demo.taler.net/";
- const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
- const trelStr = parsedUri.query?.get("tRel") ?? undefined;
- let timestamp: AbsoluteTime;
- if (trelStr) {
- timestamp = AbsoluteTime.subtractDuraction(
- AbsoluteTime.now(),
- Duration.fromPrettyString(trelStr),
- );
- } else {
- timestamp = AbsoluteTime.now();
- }
- const ct: PeerContractTerms = {
- amount: Amounts.stringify(amountEffective),
- purse_expiration: AbsoluteTime.toProtocolTimestamp(timestamp),
- summary,
- };
- const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
- const contractPair = await wex.cryptoApi.createEddsaKeypair({});
- const mergePair = await wex.cryptoApi.createEddsaKeypair({});
- await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
- await tx.contractTerms.put({
- contractTermsRaw: ct,
- h: contractTermsHash,
- });
- await tx.peerPushCredit.put({
- contractPriv: contractPair.priv,
- contractTermsHash,
- currency: Amounts.currencyOf(amountEffective),
- estimatedAmountEffective: Amounts.stringify(amountEffective),
- exchangeBaseUrl,
- mergePriv: mergePair.priv,
- peerPushCreditId,
- pursePub,
- status: PeerPushCreditStatus.Done,
- timestamp: timestampPreciseToDb(
- AbsoluteTime.toPreciseTimestamp(timestamp),
- ),
- withdrawalGroupId: undefined,
- });
- await ctx.updateTransactionMeta(tx);
- });
- break;
- }
- default: {
- throw Error("transaction type not supported");
- }
- }
+ await addFakeTx(wex, parsedUri);
return;
}
case "flag-confirm-pay-no-wait": {
@@ -521,6 +238,297 @@ export async function applyDevExperiment(
throw Error(`dev-experiment id not understood ${parsedUri.devExperimentId}`);
}
+async function addFakeTx(
+ wex: WalletExecutionContext,
+ parsedUri: DevExperimentUri,
+): Promise<void> {
+ const txType = parsedUri.query?.get("txType") ?? "withdrawal";
+ const withdrawalGroupId = encodeCrock(getRandomBytes(32));
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
+ switch (txType) {
+ case "withdrawal": {
+ const secretSeed = encodeCrock(getRandomBytes(32));
+ const reservePair = await wex.ws.cryptoApi.createEddsaKeypair({});
+ const exchangeBaseUrl =
+ parsedUri.query?.get("exchangeBaseUrl") ??
+ "https://exchange.demo.taler.net/";
+ const trelStr = parsedUri.query?.get("tRel") ?? undefined;
+ const amountEffectiveStr = parsedUri.query?.get("amountEffective");
+ if (!amountEffectiveStr) {
+ throw Error("missing amountEffective option");
+ }
+ const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
+ let timestamp: AbsoluteTime;
+ if (trelStr) {
+ timestamp = AbsoluteTime.subtractDuraction(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString(trelStr),
+ );
+ } else {
+ timestamp = AbsoluteTime.now();
+ }
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await tx.withdrawalGroups.add({
+ denomSelUid: encodeCrock(getRandomBytes(32)),
+ reservePriv: reservePair.priv,
+ reservePub: reservePair.pub,
+ secretSeed,
+ status: WithdrawalGroupStatus.Done,
+ timestampStart: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ timestampFinish: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ withdrawalGroupId,
+ wgInfo: {
+ withdrawalType: WithdrawalRecordType.BankManual,
+ exchangeCreditAccounts: [
+ {
+ paytoUri: "payto://x-taler-bank/test/test",
+ status: "ok",
+ },
+ ],
+ },
+ denomsSel: {
+ totalCoinValue: Amounts.stringify(amountEffective),
+ hasDenomWithAgeRestriction: false,
+ totalWithdrawCost: Amounts.stringify(amountEffective),
+ selectedDenoms: [],
+ },
+ exchangeBaseUrl,
+ instructedAmount: Amounts.stringify(amountEffective),
+ effectiveWithdrawalAmount: Amounts.stringify(amountEffective),
+ rawWithdrawalAmount: Amounts.stringify(amountEffective),
+ });
+ await ctx.updateTransactionMeta(tx);
+ });
+ break;
+ }
+ case "payment": {
+ const proposalId = encodeCrock(getRandomBytes(32));
+ const ctx = new PayMerchantTransactionContext(wex, proposalId);
+ const summary = parsedUri.query?.get("summary") ?? "Test";
+ const amountEffectiveStr = parsedUri.query?.get("amountEffective");
+ if (!amountEffectiveStr) {
+ throw Error("missing amountEffective option");
+ }
+ const merchantName =
+ parsedUri.query?.get("merchantName") ?? "Test Merchant";
+ const exchangeBaseUrl =
+ parsedUri.query?.get("exchangeBaseUrl") ??
+ "https://exchange.demo.taler.net/";
+ const merchantBaseUrl =
+ parsedUri.query?.get("merchantBaseUrl") ??
+ "https://backend.demo.taler.net/";
+ const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
+ const trelStr = parsedUri.query?.get("tRel") ?? undefined;
+ let timestamp: AbsoluteTime;
+ if (trelStr) {
+ timestamp = AbsoluteTime.subtractDuraction(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString(trelStr),
+ );
+ } else {
+ timestamp = AbsoluteTime.now();
+ }
+ const orderId = encodeCrock(getRandomBytes(8));
+ const noncePair = await wex.ws.cryptoApi.createEddsaKeypair({});
+ const merchantPub = encodeCrock(getRandomBytes(32));
+ const ct: MerchantContractTermsV0 = {
+ amount: Amounts.stringify(amountEffective),
+ exchanges: [
+ {
+ master_pub: encodeCrock(getRandomBytes(32)),
+ priority: 1,
+ url: exchangeBaseUrl,
+ },
+ ],
+ h_wire: encodeCrock(getRandomBytes(64)),
+ max_fee: Amounts.stringify(Amounts.zeroOfAmount(amountEffective)),
+ timestamp: AbsoluteTime.toProtocolTimestamp(timestamp),
+ summary,
+ order_id: orderId,
+ merchant_base_url: merchantBaseUrl,
+ merchant_pub: merchantPub,
+ wire_method: "x-taler-bank",
+ version: MerchantContractVersion.V0,
+ nonce: encodeCrock(getRandomBytes(32)),
+ merchant: {
+ name: merchantName,
+ },
+ pay_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
+ refund_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
+ wire_transfer_deadline: AbsoluteTime.toProtocolTimestamp(timestamp),
+ };
+ const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await tx.contractTerms.put({
+ contractTermsRaw: ct,
+ h: contractTermsHash,
+ });
+ await tx.purchases.put({
+ autoRefundDeadline: undefined,
+ claimToken: encodeCrock(getRandomBytes(32)),
+ downloadSessionId: encodeCrock(getRandomBytes(32)),
+ orderId,
+ proposalId,
+ download: {
+ contractTermsHash,
+ contractTermsMerchantSig: encodeCrock(getRandomBytes(64)),
+ currency: Amounts.currencyOf(amountEffective),
+ },
+ merchantBaseUrl,
+ purchaseStatus: PurchaseStatus.Done,
+ repurchaseProposalId: undefined,
+ lastSessionId: undefined,
+ merchantPaySig: encodeCrock(getRandomBytes(64)),
+ noncePriv: noncePair.priv,
+ noncePub: noncePair.pub,
+ payInfo: {
+ totalPayCost: Amounts.stringify(amountEffective),
+ },
+ posConfirmation: undefined,
+ secretSeed: encodeCrock(getRandomBytes(32)),
+ timestamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ shared: false,
+ timestampFirstSuccessfulPay: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ timestampAccept: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ timestampLastRefundStatus: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ refundAmountAwaiting: undefined,
+ });
+ await ctx.updateTransactionMeta(tx);
+ });
+ break;
+ }
+ case "peer-push-debit": {
+ const pursePair = await wex.cryptoApi.createEddsaKeypair({});
+ const pursePub = pursePair.pub;
+ const ctx = new PeerPushDebitTransactionContext(wex, pursePub);
+ const summary = parsedUri.query?.get("summary") ?? "Test";
+ const amountEffectiveStr = parsedUri.query?.get("amountEffective");
+ if (!amountEffectiveStr) {
+ throw Error("missing amountEffective option");
+ }
+ const exchangeBaseUrl =
+ parsedUri.query?.get("exchangeBaseUrl") ??
+ "https://exchange.demo.taler.net/";
+ const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
+ const trelStr = parsedUri.query?.get("tRel") ?? undefined;
+ let timestamp: AbsoluteTime;
+ if (trelStr) {
+ timestamp = AbsoluteTime.subtractDuraction(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString(trelStr),
+ );
+ } else {
+ timestamp = AbsoluteTime.now();
+ }
+ const ct: PeerContractTerms = {
+ amount: Amounts.stringify(amountEffective),
+ purse_expiration: AbsoluteTime.toProtocolTimestamp(timestamp),
+ summary,
+ };
+ const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
+ const contractPair = await wex.cryptoApi.createEddsaKeypair({});
+ const mergePair = await wex.cryptoApi.createEddsaKeypair({});
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await tx.contractTerms.put({
+ contractTermsRaw: ct,
+ h: contractTermsHash,
+ });
+ await tx.peerPushDebit.put({
+ amount: Amounts.stringify(amountEffective),
+ contractEncNonce: encodeCrock(getRandomBytes(32)),
+ contractPriv: contractPair.priv,
+ contractPub: contractPair.pub,
+ contractTermsHash: contractTermsHash,
+ exchangeBaseUrl,
+ mergePriv: mergePair.priv,
+ mergePub: mergePair.pub,
+ purseExpiration: timestampProtocolToDb(ct.purse_expiration),
+ pursePriv: pursePair.priv,
+ pursePub: pursePair.pub,
+ status: PeerPushDebitStatus.Done,
+ timestampCreated: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ totalCost: Amounts.stringify(amountEffective),
+ });
+ await ctx.updateTransactionMeta(tx);
+ });
+ break;
+ }
+ case "peer-push-credit": {
+ const pursePair = await wex.cryptoApi.createEddsaKeypair({});
+ const pursePub = pursePair.pub;
+ const peerPushCreditId = encodeCrock(getRandomBytes(32));
+ const ctx = new PeerPushCreditTransactionContext(wex, pursePub);
+ const summary = parsedUri.query?.get("summary") ?? "Test";
+ const amountEffectiveStr = parsedUri.query?.get("amountEffective");
+ if (!amountEffectiveStr) {
+ throw Error("missing amountEffective option");
+ }
+ const exchangeBaseUrl =
+ parsedUri.query?.get("exchangeBaseUrl") ??
+ "https://exchange.demo.taler.net/";
+ const amountEffective = Amounts.parseOrThrow(amountEffectiveStr);
+ const trelStr = parsedUri.query?.get("tRel") ?? undefined;
+ let timestamp: AbsoluteTime;
+ if (trelStr) {
+ timestamp = AbsoluteTime.subtractDuraction(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString(trelStr),
+ );
+ } else {
+ timestamp = AbsoluteTime.now();
+ }
+ const ct: PeerContractTerms = {
+ amount: Amounts.stringify(amountEffective),
+ purse_expiration: AbsoluteTime.toProtocolTimestamp(timestamp),
+ summary,
+ };
+ const contractTermsHash = ContractTermsUtil.hashContractTerms(ct);
+ const contractPair = await wex.cryptoApi.createEddsaKeypair({});
+ const mergePair = await wex.cryptoApi.createEddsaKeypair({});
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await tx.contractTerms.put({
+ contractTermsRaw: ct,
+ h: contractTermsHash,
+ });
+ await tx.peerPushCredit.put({
+ contractPriv: contractPair.priv,
+ contractTermsHash,
+ currency: Amounts.currencyOf(amountEffective),
+ estimatedAmountEffective: Amounts.stringify(amountEffective),
+ exchangeBaseUrl,
+ mergePriv: mergePair.priv,
+ peerPushCreditId,
+ pursePub,
+ status: PeerPushCreditStatus.Done,
+ timestamp: timestampPreciseToDb(
+ AbsoluteTime.toPreciseTimestamp(timestamp),
+ ),
+ withdrawalGroupId: undefined,
+ });
+ await ctx.updateTransactionMeta(tx);
+ });
+ break;
+ }
+ default: {
+ throw Error("transaction type not supported");
+ }
+ }
+}
+
function mockResponseJson(resp: HttpResponse, respJson: any): HttpResponse {
const textEncoder = new TextEncoder();
return {