aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-integrationtests/src/test-tipping.ts6
-rw-r--r--packages/taler-wallet-core/src/TalerErrorCode.ts10
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts5
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts131
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts98
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts9
-rw-r--r--packages/taler-wallet-core/src/types/dbTypes.ts40
-rw-r--r--packages/taler-wallet-core/src/types/notifications.ts3
-rw-r--r--packages/taler-wallet-core/src/types/pending.ts3
-rw-r--r--packages/taler-wallet-core/src/types/talerTypes.ts22
-rw-r--r--packages/taler-wallet-core/src/types/walletTypes.ts8
-rw-r--r--packages/taler-wallet-core/src/wallet.ts5
13 files changed, 167 insertions, 174 deletions
diff --git a/packages/taler-integrationtests/src/test-tipping.ts b/packages/taler-integrationtests/src/test-tipping.ts
index ddf56c0e0..f7840f5da 100644
--- a/packages/taler-integrationtests/src/test-tipping.ts
+++ b/packages/taler-integrationtests/src/test-tipping.ts
@@ -94,13 +94,19 @@ runTest(async (t: GlobalTestState) => {
console.log(ptr);
+ t.assertAmountEquals(ptr.tipAmountRaw, "TESTKUDOS:5");
+ t.assertAmountEquals(ptr.tipAmountEffective, "TESTKUDOS:4.85");
+
await wallet.acceptTip({
walletTipId: ptr.walletTipId,
});
+
await wallet.runUntilDone();
const bal = await wallet.getBalances();
console.log(bal);
+
+ t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:4.85");
});
diff --git a/packages/taler-wallet-core/src/TalerErrorCode.ts b/packages/taler-wallet-core/src/TalerErrorCode.ts
index 8a020b9da..e1f777f25 100644
--- a/packages/taler-wallet-core/src/TalerErrorCode.ts
+++ b/packages/taler-wallet-core/src/TalerErrorCode.ts
@@ -22,6 +22,8 @@
*/
export enum TalerErrorCode {
+
+
/**
* Special code to indicate no error (or no "code" present).
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
@@ -3271,9 +3273,17 @@ export enum TalerErrorCode {
WALLET_WITHDRAWAL_GROUP_INCOMPLETE = 7015,
/**
+ * The signature on a coin by the exchange's denomination key (obtained through the merchant via tipping) is invalid after unblinding it.
+ * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
+ * (A value of 0 indicates that the error is generated client-side).
+ */
+ WALLET_TIPPING_COIN_SIGNATURE_INVALID = 7016,
+
+ /**
* End of error code range.
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
* (A value of 0 indicates that the error is generated client-side).
*/
END = 9999,
+
}
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 91a55c705..7dda1214d 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -286,7 +286,6 @@ async function gatherWithdrawalPending(
givesLifeness: true,
numCoinsTotal,
numCoinsWithdrawn,
- source: wsr.source,
withdrawalGroupId: wsr.withdrawalGroupId,
lastError: wsr.lastError,
retryInfo: wsr.retryInfo,
diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts
index 69942fe94..b4fa3b23e 100644
--- a/packages/taler-wallet-core/src/operations/reserves.ts
+++ b/packages/taler-wallet-core/src/operations/reserves.ts
@@ -818,10 +818,7 @@ async function depleteReserve(
const withdrawalRecord: WithdrawalGroupRecord = {
withdrawalGroupId: withdrawalGroupId,
exchangeBaseUrl: newReserve.exchangeBaseUrl,
- source: {
- type: WithdrawalSourceType.Reserve,
- reservePub: newReserve.reservePub,
- },
+ reservePub: newReserve.reservePub,
rawWithdrawalAmount: withdrawAmount,
timestampStart: getTimestampNow(),
retryInfo: initRetryInfo(),
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index 6fe374bf0..6ccd262b0 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -31,6 +31,9 @@ import {
updateRetryInfoTimeout,
WithdrawalSourceType,
TipPlanchet,
+ CoinRecord,
+ CoinSourceType,
+ CoinStatus,
} from "../types/dbTypes";
import {
getExchangeWithdrawalInfo,
@@ -40,13 +43,14 @@ import {
} from "./withdraw";
import { updateExchangeFromUrl } from "./exchanges";
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
-import { guardOperationException } from "./errors";
+import { guardOperationException, makeErrorDetails } from "./errors";
import { NotificationType } from "../types/notifications";
import { getTimestampNow } from "../util/time";
import { readSuccessResponseJsonOrThrow } from "../util/http";
import { URL } from "../util/url";
import { Logger } from "../util/logging";
import { checkDbInvariant } from "../util/invariants";
+import { TalerErrorCode } from "../TalerErrorCode";
const logger = new Logger("operations/tip.ts");
@@ -99,7 +103,7 @@ export async function prepareTip(
walletTipId: walletTipId,
acceptedTimestamp: undefined,
rejectedTimestamp: undefined,
- amount,
+ tipAmountRaw: amount,
deadline: tipPickupStatus.expiration,
exchangeUrl: tipPickupStatus.exchange_url,
merchantBaseUrl: res.merchantBaseUrl,
@@ -109,10 +113,10 @@ export async function prepareTip(
response: undefined,
createdTimestamp: getTimestampNow(),
merchantTipId: res.merchantTipId,
- totalFees: Amounts.add(
+ tipAmountEffective: Amounts.sub(amount, Amounts.add(
withdrawDetails.overhead,
withdrawDetails.withdrawFee,
- ).amount,
+ ).amount).amount,
retryInfo: initRetryInfo(),
lastError: undefined,
denomsSel: denomSelectionInfoToState(selectedDenoms),
@@ -122,10 +126,10 @@ export async function prepareTip(
const tipStatus: PrepareTipResult = {
accepted: !!tipRecord && !!tipRecord.acceptedTimestamp,
- amount: Amounts.stringify(tipPickupStatus.tip_amount),
+ tipAmountRaw: Amounts.stringify(tipPickupStatus.tip_amount),
exchangeBaseUrl: tipPickupStatus.exchange_url,
expirationTimestamp: tipPickupStatus.expiration,
- totalFees: Amounts.stringify(tipRecord.totalFees),
+ tipAmountEffective: Amounts.stringify(tipRecord.tipAmountEffective),
walletTipId: tipRecord.walletTipId,
};
@@ -182,13 +186,13 @@ async function resetTipRetry(
async function processTipImpl(
ws: InternalWalletState,
- tipId: string,
+ walletTipId: string,
forceNow: boolean,
): Promise<void> {
if (forceNow) {
- await resetTipRetry(ws, tipId);
+ await resetTipRetry(ws, walletTipId);
}
- let tipRecord = await ws.db.get(Stores.tips, tipId);
+ let tipRecord = await ws.db.get(Stores.tips, walletTipId);
if (!tipRecord) {
return;
}
@@ -216,7 +220,7 @@ async function processTipImpl(
planchets.push(r);
}
}
- await ws.db.mutate(Stores.tips, tipId, (r) => {
+ await ws.db.mutate(Stores.tips, walletTipId, (r) => {
if (!r.planchets) {
r.planchets = planchets;
}
@@ -224,7 +228,7 @@ async function processTipImpl(
});
}
- tipRecord = await ws.db.get(Stores.tips, tipId);
+ tipRecord = await ws.db.get(Stores.tips, walletTipId);
checkDbInvariant(!!tipRecord, "tip record should be in database");
checkDbInvariant(!!tipRecord.planchets, "tip record should have planchets");
@@ -246,55 +250,68 @@ async function processTipImpl(
codecForTipResponse(),
);
- if (response.reserve_sigs.length !== tipRecord.planchets.length) {
+ if (response.blind_sigs.length !== tipRecord.planchets.length) {
throw Error("number of tip responses does not match requested planchets");
}
- const withdrawalGroupId = encodeCrock(getRandomBytes(32));
- const planchets: PlanchetRecord[] = [];
-
- for (let i = 0; i < tipRecord.planchets.length; i++) {
- const tipPlanchet = tipRecord.planchets[i];
- const coinEvHash = await ws.cryptoApi.hashEncoded(tipPlanchet.coinEv);
- const planchet: PlanchetRecord = {
- blindingKey: tipPlanchet.blindingKey,
- coinEv: tipPlanchet.coinEv,
- coinPriv: tipPlanchet.coinPriv,
- coinPub: tipPlanchet.coinPub,
- coinValue: tipPlanchet.coinValue,
- denomPub: tipPlanchet.denomPub,
- denomPubHash: tipPlanchet.denomPubHash,
- reservePub: response.reserve_pub,
- withdrawSig: response.reserve_sigs[i].reserve_sig,
- isFromTip: true,
- coinEvHash,
- coinIdx: i,
- withdrawalDone: false,
- withdrawalGroupId: withdrawalGroupId,
- lastError: undefined,
- };
- planchets.push(planchet);
- }
+ const newCoinRecords: CoinRecord[] = [];
- const withdrawalGroup: WithdrawalGroupRecord = {
- exchangeBaseUrl: tipRecord.exchangeUrl,
- source: {
- type: WithdrawalSourceType.Tip,
- tipId: tipRecord.walletTipId,
- },
- timestampStart: getTimestampNow(),
- withdrawalGroupId: withdrawalGroupId,
- rawWithdrawalAmount: tipRecord.amount,
- retryInfo: initRetryInfo(),
- timestampFinish: undefined,
- lastError: undefined,
- denomsSel: tipRecord.denomsSel,
- };
+ for (let i = 0; i < response.blind_sigs.length; i++) {
+ const blindedSig = response.blind_sigs[i].blind_sig;
+
+ const planchet = tipRecord.planchets[i];
+
+ const denomSig = await ws.cryptoApi.rsaUnblind(
+ blindedSig,
+ planchet.blindingKey,
+ planchet.denomPub,
+ );
+
+ const isValid = await ws.cryptoApi.rsaVerify(
+ planchet.coinPub,
+ denomSig,
+ planchet.denomPub,
+ );
+
+ if (!isValid) {
+ await ws.db.runWithWriteTransaction([Stores.planchets], async (tx) => {
+ const tipRecord = await tx.get(Stores.tips, walletTipId);
+ if (!tipRecord) {
+ return;
+ }
+ tipRecord.lastError = makeErrorDetails(
+ TalerErrorCode.WALLET_TIPPING_COIN_SIGNATURE_INVALID,
+ "invalid signature from the exchange (via merchant tip) after unblinding",
+ {},
+ );
+ await tx.put(Stores.tips, tipRecord);
+ });
+ return;
+ }
+
+ newCoinRecords.push({
+ blindingKey: planchet.blindingKey,
+ coinPriv: planchet.coinPriv,
+ coinPub: planchet.coinPub,
+ coinSource: {
+ type: CoinSourceType.Tip,
+ coinIndex: i,
+ walletTipId: walletTipId,
+ },
+ currentAmount: planchet.coinValue,
+ denomPub: planchet.denomPub,
+ denomPubHash: planchet.denomPubHash,
+ denomSig: denomSig,
+ exchangeBaseUrl: tipRecord.exchangeUrl,
+ status: CoinStatus.Fresh,
+ suspended: false,
+ });
+ }
await ws.db.runWithWriteTransaction(
- [Stores.tips, Stores.withdrawalGroups],
+ [Stores.coins, Stores.tips, Stores.withdrawalGroups],
async (tx) => {
- const tr = await tx.get(Stores.tips, tipId);
+ const tr = await tx.get(Stores.tips, walletTipId);
if (!tr) {
return;
}
@@ -303,16 +320,12 @@ async function processTipImpl(
}
tr.pickedUp = true;
tr.retryInfo = initRetryInfo(false);
-
await tx.put(Stores.tips, tr);
- await tx.put(Stores.withdrawalGroups, withdrawalGroup);
- for (const p of planchets) {
- await tx.put(Stores.planchets, p);
+ for (const cr of newCoinRecords) {
+ await tx.put(Stores.coins, cr);
}
},
);
-
- await processWithdrawGroup(ws, withdrawalGroupId);
}
export async function acceptTip(
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 7a3228422..b5f77a190 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -116,63 +116,49 @@ export async function getTransactions(
return;
}
- switch (wsr.source.type) {
- case WithdrawalSourceType.Reserve:
- {
- const r = await tx.get(Stores.reserves, wsr.source.reservePub);
- if (!r) {
- break;
- }
- let amountRaw: AmountJson | undefined = undefined;
- if (wsr.withdrawalGroupId === r.initialWithdrawalGroupId) {
- amountRaw = r.instructedAmount;
- } else {
- amountRaw = wsr.denomsSel.totalWithdrawCost;
- }
- let withdrawalDetails: WithdrawalDetails;
- if (r.bankInfo) {
- withdrawalDetails = {
- type: WithdrawalType.TalerBankIntegrationApi,
- confirmed: true,
- bankConfirmationUrl: r.bankInfo.confirmUrl,
- };
- } else {
- const exchange = await tx.get(
- Stores.exchanges,
- r.exchangeBaseUrl,
- );
- if (!exchange) {
- // FIXME: report somehow
- break;
- }
- withdrawalDetails = {
- type: WithdrawalType.ManualTransfer,
- exchangePaytoUris:
- exchange.wireInfo?.accounts.map((x) => x.payto_uri) ?? [],
- };
- }
- transactions.push({
- type: TransactionType.Withdrawal,
- amountEffective: Amounts.stringify(
- wsr.denomsSel.totalCoinValue,
- ),
- amountRaw: Amounts.stringify(amountRaw),
- withdrawalDetails,
- exchangeBaseUrl: wsr.exchangeBaseUrl,
- pending: !wsr.timestampFinish,
- timestamp: wsr.timestampStart,
- transactionId: makeEventId(
- TransactionType.Withdrawal,
- wsr.withdrawalGroupId,
- ),
- ...(wsr.lastError ? { error: wsr.lastError } : {}),
- });
- }
- break;
- default:
- // Tips are reported via their own event
- break;
+ const r = await tx.get(Stores.reserves, wsr.reservePub);
+ if (!r) {
+ return;
+ }
+ let amountRaw: AmountJson | undefined = undefined;
+ if (wsr.withdrawalGroupId === r.initialWithdrawalGroupId) {
+ amountRaw = r.instructedAmount;
+ } else {
+ amountRaw = wsr.denomsSel.totalWithdrawCost;
+ }
+ let withdrawalDetails: WithdrawalDetails;
+ if (r.bankInfo) {
+ withdrawalDetails = {
+ type: WithdrawalType.TalerBankIntegrationApi,
+ confirmed: true,
+ bankConfirmationUrl: r.bankInfo.confirmUrl,
+ };
+ } else {
+ const exchange = await tx.get(Stores.exchanges, r.exchangeBaseUrl);
+ if (!exchange) {
+ // FIXME: report somehow
+ return;
+ }
+ withdrawalDetails = {
+ type: WithdrawalType.ManualTransfer,
+ exchangePaytoUris:
+ exchange.wireInfo?.accounts.map((x) => x.payto_uri) ?? [],
+ };
}
+ transactions.push({
+ type: TransactionType.Withdrawal,
+ amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue),
+ amountRaw: Amounts.stringify(amountRaw),
+ withdrawalDetails,
+ exchangeBaseUrl: wsr.exchangeBaseUrl,
+ pending: !wsr.timestampFinish,
+ timestamp: wsr.timestampStart,
+ transactionId: makeEventId(
+ TransactionType.Withdrawal,
+ wsr.withdrawalGroupId,
+ ),
+ ...(wsr.lastError ? { error: wsr.lastError } : {}),
+ });
});
// Report pending withdrawals based on reserves that
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 4070e39f4..eec92ba29 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -242,12 +242,9 @@ async function processPlanchetGenerate(
if (!denom) {
throw Error("invariant violated");
}
- if (withdrawalGroup.source.type != WithdrawalSourceType.Reserve) {
- throw Error("invariant violated");
- }
const reserve = await ws.db.get(
Stores.reserves,
- withdrawalGroup.source.reservePub,
+ withdrawalGroup.reservePub,
);
if (!reserve) {
throw Error("invariant violated");
@@ -420,7 +417,7 @@ async function processPlanchetVerifyAndStoreCoin(
if (!isValid) {
await ws.db.runWithWriteTransaction([Stores.planchets], async (tx) => {
- let planchet = await ws.db.getIndexed(Stores.planchets.byGroupAndIndex, [
+ let planchet = await tx.getIndexed(Stores.planchets.byGroupAndIndex, [
withdrawalGroupId,
coinIdx,
]);
@@ -700,7 +697,7 @@ async function processWithdrawGroupImpl(
if (finishedForFirstTime) {
ws.notify({
type: NotificationType.WithdrawGroupFinished,
- withdrawalSource: withdrawalGroup.source,
+ reservePub: withdrawalGroup.reservePub,
});
}
}
diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts b/packages/taler-wallet-core/src/types/dbTypes.ts
index 4e2ba1bb4..3e24f787b 100644
--- a/packages/taler-wallet-core/src/types/dbTypes.ts
+++ b/packages/taler-wallet-core/src/types/dbTypes.ts
@@ -694,17 +694,28 @@ export interface PlanchetRecord {
lastError: TalerErrorDetails | undefined;
/**
- * Public key of the reserve, this might be a reserve not
- * known to the wallet if the planchet is from a tip.
+ * Public key of the reserve that this planchet
+ * is being withdrawn from.
+ *
+ * Can be the empty string (non-null/undefined for DB indexing)
+ * if this is a tipping reserve.
*/
reservePub: string;
+
denomPubHash: string;
+
denomPub: string;
+
blindingKey: string;
+
withdrawSig: string;
+
coinEv: string;
+
coinEvHash: string;
+
coinValue: AmountJson;
+
isFromTip: boolean;
}
@@ -772,6 +783,8 @@ export interface RefreshCoinSource {
export interface TipCoinSource {
type: CoinSourceType.Tip;
+ walletTipId: string;
+ coinIndex: number;
}
export type CoinSource = WithdrawCoinSource | RefreshCoinSource | TipCoinSource;
@@ -950,9 +963,9 @@ export interface TipRecord {
/**
* The tipped amount.
*/
- amount: AmountJson;
+ tipAmountRaw: AmountJson;
- totalFees: AmountJson;
+ tipAmountEffective: AmountJson;
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
@@ -1481,18 +1494,6 @@ export enum WithdrawalSourceType {
Reserve = "reserve",
}
-export interface WithdrawalSourceTip {
- type: WithdrawalSourceType.Tip;
- tipId: string;
-}
-
-export interface WithdrawalSourceReserve {
- type: WithdrawalSourceType.Reserve;
- reservePub: string;
-}
-
-export type WithdrawalSource = WithdrawalSourceTip | WithdrawalSourceReserve;
-
export interface DenominationSelectionInfo {
totalCoinValue: AmountJson;
totalWithdrawCost: AmountJson;
@@ -1524,12 +1525,7 @@ export interface DenomSelectionState {
export interface WithdrawalGroupRecord {
withdrawalGroupId: string;
- /**
- * Withdrawal source. Fields that don't apply to the respective
- * withdrawal source type must be null (i.e. can't be absent),
- * otherwise the IndexedDB indexing won't like us.
- */
- source: WithdrawalSource;
+ reservePub: string;
exchangeBaseUrl: string;
diff --git a/packages/taler-wallet-core/src/types/notifications.ts b/packages/taler-wallet-core/src/types/notifications.ts
index e1b9a7aff..d86c5ae59 100644
--- a/packages/taler-wallet-core/src/types/notifications.ts
+++ b/packages/taler-wallet-core/src/types/notifications.ts
@@ -23,7 +23,6 @@
* Imports.
*/
import { TalerErrorDetails } from "./walletTypes";
-import { WithdrawalSource } from "./dbTypes";
import { ReserveHistorySummary } from "../util/reserveHistoryUtil";
export enum NotificationType {
@@ -141,7 +140,7 @@ export interface WithdrawalGroupCreatedNotification {
export interface WithdrawalGroupFinishedNotification {
type: NotificationType.WithdrawGroupFinished;
- withdrawalSource: WithdrawalSource;
+ reservePub: string;
}
export interface WaitingForRetryNotification {
diff --git a/packages/taler-wallet-core/src/types/pending.ts b/packages/taler-wallet-core/src/types/pending.ts
index d07754fe9..b14872d74 100644
--- a/packages/taler-wallet-core/src/types/pending.ts
+++ b/packages/taler-wallet-core/src/types/pending.ts
@@ -22,7 +22,7 @@
* Imports.
*/
import { TalerErrorDetails, BalancesResponse } from "./walletTypes";
-import { WithdrawalSource, RetryInfo, ReserveRecordStatus } from "./dbTypes";
+import { RetryInfo, ReserveRecordStatus } from "./dbTypes";
import { Timestamp, Duration } from "../util/time";
export enum PendingOperationType {
@@ -219,7 +219,6 @@ export interface PendingRecoupOperation {
*/
export interface PendingWithdrawOperation {
type: PendingOperationType.Withdraw;
- source: WithdrawalSource;
lastError: TalerErrorDetails | undefined;
retryInfo: RetryInfo;
withdrawalGroupId: string;
diff --git a/packages/taler-wallet-core/src/types/talerTypes.ts b/packages/taler-wallet-core/src/types/talerTypes.ts
index 52dc4cb62..16d00e2ea 100644
--- a/packages/taler-wallet-core/src/types/talerTypes.ts
+++ b/packages/taler-wallet-core/src/types/talerTypes.ts
@@ -593,11 +593,11 @@ export interface TipPickupRequest {
* Reserve signature, defined as separate class to facilitate
* schema validation with "@Checkable".
*/
-export class ReserveSigSingleton {
+export class BlindSigWrapper {
/**
* Reserve signature.
*/
- reserve_sig: string;
+ blind_sig: string;
}
/**
@@ -606,14 +606,9 @@ export class ReserveSigSingleton {
*/
export class TipResponse {
/**
- * Public key of the reserve
- */
- reserve_pub: string;
-
- /**
* The order of the signatures matches the planchets list.
*/
- reserve_sigs: ReserveSigSingleton[];
+ blind_sigs: BlindSigWrapper[];
}
/**
@@ -1166,15 +1161,14 @@ export const codecForMerchantRefundResponse = (): Codec<
.property("refunds", codecForList(codecForMerchantRefundPermission()))
.build("MerchantRefundResponse");
-export const codecForReserveSigSingleton = (): Codec<ReserveSigSingleton> =>
- buildCodecForObject<ReserveSigSingleton>()
- .property("reserve_sig", codecForString())
- .build("ReserveSigSingleton");
+export const codecForBlindSigWrapper = (): Codec<BlindSigWrapper> =>
+ buildCodecForObject<BlindSigWrapper>()
+ .property("blind_sig", codecForString())
+ .build("BlindSigWrapper");
export const codecForTipResponse = (): Codec<TipResponse> =>
buildCodecForObject<TipResponse>()
- .property("reserve_pub", codecForString())
- .property("reserve_sigs", codecForList(codecForReserveSigSingleton()))
+ .property("blind_sigs", codecForList(codecForBlindSigWrapper()))
.build("TipResponse");
export const codecForRecoup = (): Codec<Recoup> =>
diff --git a/packages/taler-wallet-core/src/types/walletTypes.ts b/packages/taler-wallet-core/src/types/walletTypes.ts
index fb049caf9..c9014830b 100644
--- a/packages/taler-wallet-core/src/types/walletTypes.ts
+++ b/packages/taler-wallet-core/src/types/walletTypes.ts
@@ -359,8 +359,8 @@ export interface PrepareTipResult {
* Has the tip already been accepted?
*/
accepted: boolean;
- amount: AmountString;
- totalFees: AmountString;
+ tipAmountRaw: AmountString;
+ tipAmountEffective: AmountString;
exchangeBaseUrl: string;
expirationTimestamp: Timestamp;
}
@@ -368,8 +368,8 @@ export interface PrepareTipResult {
export const codecForPrepareTipResult = (): Codec<PrepareTipResult> =>
buildCodecForObject<PrepareTipResult>()
.property("accepted", codecForBoolean())
- .property("amount", codecForAmountString())
- .property("totalFees", codecForAmountString())
+ .property("tipAmountRaw", codecForAmountString())
+ .property("tipAmountEffective", codecForAmountString())
.property("exchangeBaseUrl", codecForString())
.property("expirationTimestamp", codecForTimestamp)
.property("walletTipId", codecForString())
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 0507ac8b2..cd9646339 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -86,7 +86,6 @@ import {
codecForPreparePayRequest,
codecForIntegrationTestArgs,
WithdrawTestBalanceRequest,
- withdrawTestBalanceDefaults,
codecForWithdrawTestBalance,
codecForTestPayArgs,
codecForSetCoinSuspendedRequest,
@@ -916,9 +915,7 @@ export class Wallet {
console.error("no withdrawal session found for coin");
continue;
}
- if (ws.source.type == "reserve") {
- withdrawalReservePub = ws.source.reservePub;
- }
+ withdrawalReservePub = ws.reservePub;
}
coinsJson.coins.push({
coin_pub: c.coinPub,