-towards tip->reward rename

This commit is contained in:
Florian Dold 2023-08-03 18:35:07 +02:00
parent 0fe4840ca2
commit fdbd55d2bd
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
31 changed files with 372 additions and 368 deletions

View File

@ -51,8 +51,8 @@ import {
stringToBytes,
TalerError,
TalerProtocolDuration,
TipCreateConfirmation,
TipCreateRequest,
RewardCreateConfirmation,
RewardCreateRequest,
TippingReserveStatus,
WalletNotification,
} from "@gnu-taler/taler-util";
@ -1751,8 +1751,8 @@ export namespace MerchantPrivateApi {
export async function giveTip(
merchantService: MerchantServiceInterface,
instance: string,
req: TipCreateRequest,
): Promise<TipCreateConfirmation> {
req: RewardCreateRequest,
): Promise<RewardCreateConfirmation> {
const reqUrl = new URL(
`private/tips`,
merchantService.makeInstanceBaseUrl(instance),

View File

@ -191,12 +191,12 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
const walletTipping = new WalletCli(t, "age-tipping");
const ptr = await walletTipping.client.call(WalletApiOperation.PrepareTip, {
talerTipUri: tip.taler_tip_uri,
const ptr = await walletTipping.client.call(WalletApiOperation.PrepareReward, {
talerRewardUri: tip.taler_reward_uri,
});
await walletTipping.client.call(WalletApiOperation.AcceptTip, {
walletTipId: ptr.walletTipId,
await walletTipping.client.call(WalletApiOperation.AcceptReward, {
walletRewardId: ptr.walletRewardId,
});
await walletTipping.runUntilDone();

View File

@ -99,17 +99,17 @@ export async function runTippingTest(t: GlobalTestState) {
console.log("created tip", tip);
const doTip = async (): Promise<void> => {
const ptr = await wallet.client.call(WalletApiOperation.PrepareTip, {
talerTipUri: tip.taler_tip_uri,
const ptr = await wallet.client.call(WalletApiOperation.PrepareReward, {
talerRewardUri: tip.taler_reward_uri,
});
console.log(ptr);
t.assertAmountEquals(ptr.tipAmountRaw, "TESTKUDOS:5");
t.assertAmountEquals(ptr.tipAmountEffective, "TESTKUDOS:4.85");
t.assertAmountEquals(ptr.rewardAmountRaw, "TESTKUDOS:5");
t.assertAmountEquals(ptr.rewardAmountEffective, "TESTKUDOS:4.85");
await wallet.client.call(WalletApiOperation.AcceptTip, {
walletTipId: ptr.walletTipId,
await wallet.client.call(WalletApiOperation.AcceptReward, {
walletRewardId: ptr.walletRewardId,
});
await wallet.runUntilDone();
@ -127,7 +127,7 @@ export async function runTippingTest(t: GlobalTestState) {
console.log("Transactions:", JSON.stringify(txns, undefined, 2));
t.assertDeepEqual(txns.transactions[0].type, "tip");
t.assertDeepEqual(txns.transactions[0].type, "reward");
t.assertDeepEqual(txns.transactions[0].txState.major, TransactionMajorState.Done);
t.assertAmountEquals(
txns.transactions[0].amountEffective,

View File

@ -499,7 +499,7 @@ export interface BackupRecoupGroup {
export enum BackupCoinSourceType {
Withdraw = "withdraw",
Refresh = "refresh",
Tip = "tip",
Reward = "reward",
}
/**
@ -546,7 +546,7 @@ export interface BackupRefreshCoinSource {
* Metadata about a coin obtained from a tip.
*/
export interface BackupTipCoinSource {
type: BackupCoinSourceType.Tip;
type: BackupCoinSourceType.Reward;
/**
* Wallet's identifier for the tip that this coin

View File

@ -183,7 +183,16 @@ export class HttpLibImpl implements HttpRequestLibrary {
resolve(resp);
});
res.on("error", (e) => {
reject(e);
const err = TalerError.fromDetail(
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
{
requestUrl: url,
requestMethod: method,
httpStatusCode: 0,
},
`Error in HTTP response handler: ${e.message}`,
);
reject(err);
});
};
@ -197,7 +206,16 @@ export class HttpLibImpl implements HttpRequestLibrary {
}
req.on("error", (e: Error) => {
reject(e);
const err = TalerError.fromDetail(
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
{
requestUrl: url,
requestMethod: method,
httpStatusCode: 0,
},
`Error in HTTP request: ${e.message}`,
);
reject(err);
});
if (reqBody) {

View File

@ -290,22 +290,22 @@ export interface ReserveStatusEntry {
active: boolean;
}
export interface TipCreateConfirmation {
export interface RewardCreateConfirmation {
// Unique tip identifier for the tip that was created.
tip_id: string;
reward_id: string;
// taler://tip URI for the tip
taler_tip_uri: string;
taler_reward_uri: string;
// URL that will directly trigger processing
// the tip when the browser is redirected to it
tip_status_url: string;
reward_status_url: string;
// when does the tip expire
tip_expiration: AbsoluteTime;
// when does the reward expire
reward_expiration: AbsoluteTime;
}
export interface TipCreateRequest {
export interface RewardCreateRequest {
// Amount that the customer should be tipped
amount: AmountString;

View File

@ -186,7 +186,7 @@ export type Transaction =
| TransactionWithdrawal
| TransactionPayment
| TransactionRefund
| TransactionTip
| TransactionReward
| TransactionRefresh
| TransactionDeposit
| TransactionPeerPullCredit
@ -201,7 +201,7 @@ export enum TransactionType {
Payment = "payment",
Refund = "refund",
Refresh = "refresh",
Tip = "tip",
Reward = "reward",
Deposit = "deposit",
PeerPushDebit = "peer-push-debit",
PeerPushCredit = "peer-push-credit",
@ -591,8 +591,8 @@ export interface TransactionRefund extends TransactionCommon {
paymentInfo: RefundPaymentInfo | undefined;
}
export interface TransactionTip extends TransactionCommon {
type: TransactionType.Tip;
export interface TransactionReward extends TransactionCommon {
type: TransactionType.Reward;
// Raw amount of the tip, without extra fees that apply
amountRaw: AmountString;

View File

@ -605,7 +605,7 @@ export interface PrepareTipResult {
*
* @deprecated use transactionId instead
*/
walletTipId: string;
walletRewardId: string;
/**
* Tip transaction ID.
@ -620,13 +620,13 @@ export interface PrepareTipResult {
/**
* Amount that the merchant gave.
*/
tipAmountRaw: AmountString;
rewardAmountRaw: AmountString;
/**
* Amount that arrived at the wallet.
* Might be lower than the raw amount due to fees.
*/
tipAmountEffective: AmountString;
rewardAmountEffective: AmountString;
/**
* Base URL of the merchant backend giving then tip.
@ -654,14 +654,14 @@ export interface AcceptTipResponse {
export const codecForPrepareTipResult = (): Codec<PrepareTipResult> =>
buildCodecForObject<PrepareTipResult>()
.property("accepted", codecForBoolean())
.property("tipAmountRaw", codecForAmountString())
.property("tipAmountEffective", codecForAmountString())
.property("rewardAmountRaw", codecForAmountString())
.property("rewardAmountEffective", codecForAmountString())
.property("exchangeBaseUrl", codecForString())
.property("merchantBaseUrl", codecForString())
.property("expirationTimestamp", codecForTimestamp)
.property("walletTipId", codecForString())
.property("walletRewardId", codecForString())
.property("transactionId", codecForString())
.build("PrepareTipResult");
.build("PrepareRewardResult");
export interface BenchmarkResult {
time: { [s: string]: number };
@ -1933,23 +1933,23 @@ export const codecForStartRefundQueryRequest =
.property("transactionId", codecForTransactionIdStr())
.build("StartRefundQueryRequest");
export interface PrepareTipRequest {
talerTipUri: string;
export interface PrepareRewardRequest {
talerRewardUri: string;
}
export const codecForPrepareTipRequest = (): Codec<PrepareTipRequest> =>
buildCodecForObject<PrepareTipRequest>()
.property("talerTipUri", codecForString())
.build("PrepareTipRequest");
export const codecForPrepareRewardRequest = (): Codec<PrepareRewardRequest> =>
buildCodecForObject<PrepareRewardRequest>()
.property("talerRewardUri", codecForString())
.build("PrepareRewardRequest");
export interface AcceptTipRequest {
walletTipId: string;
export interface AcceptRewardRequest {
walletRewardId: string;
}
export const codecForAcceptTipRequest = (): Codec<AcceptTipRequest> =>
buildCodecForObject<AcceptTipRequest>()
.property("walletTipId", codecForString())
.build("AcceptTipRequest");
export const codecForAcceptTipRequest = (): Codec<AcceptRewardRequest> =>
buildCodecForObject<AcceptRewardRequest>()
.property("walletRewardId", codecForString())
.build("AcceptRewardRequest");
export interface FailTransactionRequest {
transactionId: TransactionIdStr;

View File

@ -652,12 +652,12 @@ walletCli
});
break;
case TalerUriAction.Tip: {
const res = await wallet.client.call(WalletApiOperation.PrepareTip, {
talerTipUri: uri,
const res = await wallet.client.call(WalletApiOperation.PrepareReward, {
talerRewardUri: uri,
});
console.log("tip status", res);
await wallet.client.call(WalletApiOperation.AcceptTip, {
walletTipId: res.walletTipId,
await wallet.client.call(WalletApiOperation.AcceptReward, {
walletRewardId: res.walletRewardId,
});
break;
}

View File

@ -677,7 +677,7 @@ export interface PlanchetRecord {
export enum CoinSourceType {
Withdraw = "withdraw",
Refresh = "refresh",
Tip = "tip",
Reward = "reward",
}
export interface WithdrawCoinSource {
@ -705,13 +705,13 @@ export interface RefreshCoinSource {
oldCoinPub: string;
}
export interface TipCoinSource {
type: CoinSourceType.Tip;
walletTipId: string;
export interface RewardCoinSource {
type: CoinSourceType.Reward;
walletRewardId: string;
coinIndex: number;
}
export type CoinSource = WithdrawCoinSource | RefreshCoinSource | TipCoinSource;
export type CoinSource = WithdrawCoinSource | RefreshCoinSource | RewardCoinSource;
/**
* CoinRecord as stored in the "coins" data store
@ -815,9 +815,9 @@ export interface CoinAllocation {
}
/**
* Status of a tip we got from a merchant.
* Status of a reward we got from a merchant.
*/
export interface TipRecord {
export interface RewardRecord {
/**
* Has the user accepted the tip? Only after the tip has been accepted coins
* withdrawn from the tip may be used.
@ -827,17 +827,17 @@ export interface TipRecord {
/**
* The tipped amount.
*/
tipAmountRaw: AmountString;
rewardAmountRaw: AmountString;
/**
* Effect on the balance (including fees etc).
*/
tipAmountEffective: AmountString;
rewardAmountEffective: AmountString;
/**
* Timestamp, the tip can't be picked up anymore after this deadline.
*/
tipExpiration: TalerProtocolTimestamp;
rewardExpiration: TalerProtocolTimestamp;
/**
* The exchange that will sign our coins, chosen by the merchant.
@ -863,7 +863,7 @@ export interface TipRecord {
/**
* Tip ID chosen by the wallet.
*/
walletTipId: string;
walletRewardId: string;
/**
* Secret seed used to derive planchets for this tip.
@ -871,9 +871,9 @@ export interface TipRecord {
secretSeed: string;
/**
* The merchant's identifier for this tip.
* The merchant's identifier for this reward.
*/
merchantTipId: string;
merchantRewardId: string;
createdTimestamp: TalerPreciseTimestamp;
@ -888,10 +888,10 @@ export interface TipRecord {
*/
pickedUpTimestamp: TalerPreciseTimestamp | undefined;
status: TipRecordStatus;
status: RewardRecordStatus;
}
export enum TipRecordStatus {
export enum RewardRecordStatus {
PendingPickup = 10,
SuspendidPickup = 20,
@ -1420,7 +1420,7 @@ export interface KycPendingInfo {
}
/**
* Group of withdrawal operations that need to be executed.
* (Either for a normal withdrawal or from a tip.)
* (Either for a normal withdrawal or from a reward.)
*
* The withdrawal group record is only created after we know
* the coin selection we want to withdraw.
@ -2480,12 +2480,12 @@ export const WalletStoresV1 = {
]),
},
),
tips: describeStore(
"tips",
describeContents<TipRecord>({ keyPath: "walletTipId" }),
rewards: describeStore(
"rewards",
describeContents<RewardRecord>({ keyPath: "walletRewardId" }),
{
byMerchantTipIdAndBaseUrl: describeIndex("byMerchantTipIdAndBaseUrl", [
"merchantTipId",
byMerchantTipIdAndBaseUrl: describeIndex("byMerchantRewardIdAndBaseUrl", [
"merchantRewardId",
"merchantBaseUrl",
]),
byStatus: describeIndex("byStatus", "status", {
@ -2935,22 +2935,6 @@ export const walletDbFixups: FixupDescription[] = [
});
},
},
{
name: "TipRecordRecord_status_add",
async fn(tx): Promise<void> {
await tx.tips.iter().forEachAsync(async (r) => {
// Remove legacy transactions that don't have the totalCost field yet.
if (r.status == null) {
if (r.pickedUpTimestamp) {
r.status = TipRecordStatus.Done;
} else {
r.status = TipRecordStatus.PendingPickup;
}
await tx.tips.put(r);
}
});
},
},
{
name: "CoinAvailabilityRecord_visibleCoinCount_add",
async fn(tx): Promise<void> {

View File

@ -96,7 +96,7 @@ export async function exportBackup(
x.purchases,
x.refreshGroups,
x.backupProviders,
x.tips,
x.rewards,
x.recoupGroups,
x.withdrawalGroups,
])
@ -184,12 +184,12 @@ export async function exportBackup(
});
});
await tx.tips.iter().forEach((tip) => {
await tx.rewards.iter().forEach((tip) => {
backupTips.push({
exchange_base_url: tip.exchangeBaseUrl,
merchant_base_url: tip.merchantBaseUrl,
merchant_tip_id: tip.merchantTipId,
wallet_tip_id: tip.walletTipId,
merchant_tip_id: tip.merchantRewardId,
wallet_tip_id: tip.walletRewardId,
next_url: tip.next_url,
secret_seed: tip.secretSeed,
selected_denoms: tip.denomsSel.selectedDenoms.map((x) => ({
@ -199,8 +199,8 @@ export async function exportBackup(
timestamp_finished: tip.pickedUpTimestamp,
timestamp_accepted: tip.acceptedTimestamp,
timestamp_created: tip.createdTimestamp,
timestamp_expiration: tip.tipExpiration,
tip_amount_raw: Amounts.stringify(tip.tipAmountRaw),
timestamp_expiration: tip.rewardExpiration,
tip_amount_raw: Amounts.stringify(tip.rewardAmountRaw),
selected_denoms_uid: tip.denomSelUid,
});
});
@ -244,11 +244,11 @@ export async function exportBackup(
refresh_group_id: coin.coinSource.refreshGroupId,
};
break;
case CoinSourceType.Tip:
case CoinSourceType.Reward:
bcs = {
type: BackupCoinSourceType.Tip,
type: BackupCoinSourceType.Reward,
coin_index: coin.coinSource.coinIndex,
wallet_tip_id: coin.coinSource.walletTipId,
wallet_tip_id: coin.coinSource.walletRewardId,
};
break;
case CoinSourceType.Withdraw:

View File

@ -56,7 +56,7 @@ import {
WithdrawalGroupStatus,
WithdrawalRecordType,
RefreshOperationStatus,
TipRecordStatus,
RewardRecordStatus,
} from "../../db.js";
import { InternalWalletState } from "../../internal-wallet-state.js";
import { assertUnreachable } from "../../util/assertUnreachable.js";
@ -250,11 +250,11 @@ export async function importCoin(
refreshGroupId: backupCoin.coin_source.refresh_group_id,
};
break;
case BackupCoinSourceType.Tip:
case BackupCoinSourceType.Reward:
coinSource = {
type: CoinSourceType.Tip,
type: CoinSourceType.Reward,
coinIndex: backupCoin.coin_source.coin_index,
walletTipId: backupCoin.coin_source.wallet_tip_id,
walletRewardId: backupCoin.coin_source.wallet_tip_id,
};
break;
case BackupCoinSourceType.Withdraw:
@ -311,7 +311,7 @@ export async function importBackup(
x.purchases,
x.refreshGroups,
x.backupProviders,
x.tips,
x.rewards,
x.recoupGroups,
x.withdrawalGroups,
x.tombstones,
@ -812,13 +812,13 @@ export async function importBackup(
for (const backupTip of backupBlob.tips) {
const ts = constructTombstone({
tag: TombstoneTag.DeleteTip,
tag: TombstoneTag.DeleteReward,
walletTipId: backupTip.wallet_tip_id,
});
if (tombstoneSet.has(ts)) {
continue;
}
const existingTip = await tx.tips.get(backupTip.wallet_tip_id);
const existingTip = await tx.rewards.get(backupTip.wallet_tip_id);
if (!existingTip) {
const tipAmountRaw = Amounts.parseOrThrow(backupTip.tip_amount_raw);
const denomsSel = await getDenomSelStateFromBackup(
@ -827,22 +827,22 @@ export async function importBackup(
backupTip.exchange_base_url,
backupTip.selected_denoms,
);
await tx.tips.put({
await tx.rewards.put({
acceptedTimestamp: backupTip.timestamp_accepted,
createdTimestamp: backupTip.timestamp_created,
denomsSel,
next_url: backupTip.next_url,
exchangeBaseUrl: backupTip.exchange_base_url,
merchantBaseUrl: backupTip.exchange_base_url,
merchantTipId: backupTip.merchant_tip_id,
merchantRewardId: backupTip.merchant_tip_id,
pickedUpTimestamp: backupTip.timestamp_finished,
secretSeed: backupTip.secret_seed,
tipAmountEffective: Amounts.stringify(denomsSel.totalCoinValue),
tipAmountRaw: Amounts.stringify(tipAmountRaw),
tipExpiration: backupTip.timestamp_expiration,
walletTipId: backupTip.wallet_tip_id,
rewardAmountEffective: Amounts.stringify(denomsSel.totalCoinValue),
rewardAmountRaw: Amounts.stringify(tipAmountRaw),
rewardExpiration: backupTip.timestamp_expiration,
walletRewardId: backupTip.wallet_tip_id,
denomSelUid: backupTip.selected_denoms_uid,
status: TipRecordStatus.Done, // FIXME!
status: RewardRecordStatus.Done, // FIXME!
});
}
}
@ -863,8 +863,8 @@ export async function importBackup(
} else if (type === TombstoneTag.DeleteRefund) {
// Nothing required, will just prevent display
// in the transactions list
} else if (type === TombstoneTag.DeleteTip) {
await tx.tips.delete(rest[0]);
} else if (type === TombstoneTag.DeleteReward) {
await tx.rewards.delete(rest[0]);
} else if (type === TombstoneTag.DeleteWithdrawalGroup) {
await tx.withdrawalGroups.delete(rest[0]);
} else {

View File

@ -57,7 +57,7 @@ import {
PurchaseRecord,
RecoupGroupRecord,
RefreshGroupRecord,
TipRecord,
RewardRecord,
WithdrawalGroupRecord,
} from "../db.js";
import { makeErrorDetail, TalerError } from "@gnu-taler/taler-util";
@ -293,10 +293,10 @@ function convertTaskToTransactionId(
tag: TransactionType.Refresh,
refreshGroupId: parsedTaskId.refreshGroupId,
});
case PendingTaskType.TipPickup:
case PendingTaskType.RewardPickup:
return constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId: parsedTaskId.walletTipId,
tag: TransactionType.Reward,
walletRewardId: parsedTaskId.walletRewardId,
});
case PendingTaskType.PeerPushDebit:
return constructTransactionIdentifier({
@ -515,7 +515,7 @@ export enum TombstoneTag {
DeleteWithdrawalGroup = "delete-withdrawal-group",
DeleteReserve = "delete-reserve",
DeletePayment = "delete-payment",
DeleteTip = "delete-tip",
DeleteReward = "delete-reward",
DeleteRefreshGroup = "delete-refresh-group",
DeleteDepositGroup = "delete-deposit-group",
DeleteRefund = "delete-refund",
@ -601,7 +601,9 @@ export function runLongpollAsync(
};
res = await reqFn(cts.token);
} catch (e) {
await storePendingTaskError(ws, retryTag, getErrorDetailFromException(e));
const errDetail = getErrorDetailFromException(e);
logger.warn(`got error during long-polling: ${j2s(errDetail)}`);
await storePendingTaskError(ws, retryTag, errDetail);
return;
} finally {
delete ws.activeLongpoll[retryTag];
@ -622,7 +624,7 @@ export type ParsedTombstone =
| { tag: TombstoneTag.DeleteRefund; refundGroupId: string }
| { tag: TombstoneTag.DeleteReserve; reservePub: string }
| { tag: TombstoneTag.DeleteRefreshGroup; refreshGroupId: string }
| { tag: TombstoneTag.DeleteTip; walletTipId: string }
| { tag: TombstoneTag.DeleteReward; walletTipId: string }
| { tag: TombstoneTag.DeletePayment; proposalId: string };
export function constructTombstone(p: ParsedTombstone): TombstoneIdStr {
@ -637,7 +639,7 @@ export function constructTombstone(p: ParsedTombstone): TombstoneIdStr {
return `tmb:${p.tag}:${p.proposalId}` as TombstoneIdStr;
case TombstoneTag.DeleteRefreshGroup:
return `tmb:${p.tag}:${p.refreshGroupId}` as TombstoneIdStr;
case TombstoneTag.DeleteTip:
case TombstoneTag.DeleteReward:
return `tmb:${p.tag}:${p.walletTipId}` as TombstoneIdStr;
default:
assertUnreachable(p);
@ -810,7 +812,7 @@ export type ParsedTaskIdentifier =
| { tag: PendingTaskType.PeerPushDebit; pursePub: string }
| { tag: PendingTaskType.Purchase; proposalId: string }
| { tag: PendingTaskType.Recoup; recoupGroupId: string }
| { tag: PendingTaskType.TipPickup; walletTipId: string }
| { tag: PendingTaskType.RewardPickup; walletRewardId: string }
| { tag: PendingTaskType.Refresh; refreshGroupId: string };
export function parseTaskIdentifier(x: string): ParsedTaskIdentifier {
@ -844,8 +846,8 @@ export function parseTaskIdentifier(x: string): ParsedTaskIdentifier {
return { tag: type, recoupGroupId: rest[0] };
case PendingTaskType.Refresh:
return { tag: type, refreshGroupId: rest[0] };
case PendingTaskType.TipPickup:
return { tag: type, walletTipId: rest[0] };
case PendingTaskType.RewardPickup:
return { tag: type, walletRewardId: rest[0] };
case PendingTaskType.Withdraw:
return { tag: type, withdrawalGroupId: rest[0] };
default:
@ -877,8 +879,8 @@ export function constructTaskIdentifier(p: ParsedTaskIdentifier): TaskId {
return `${p.tag}:${p.recoupGroupId}` as TaskId;
case PendingTaskType.Refresh:
return `${p.tag}:${p.refreshGroupId}` as TaskId;
case PendingTaskType.TipPickup:
return `${p.tag}:${p.walletTipId}` as TaskId;
case PendingTaskType.RewardPickup:
return `${p.tag}:${p.walletRewardId}` as TaskId;
case PendingTaskType.Withdraw:
return `${p.tag}:${p.withdrawalGroupId}` as TaskId;
default:
@ -899,8 +901,8 @@ export namespace TaskIdentifiers {
export function forExchangeCheckRefresh(exch: ExchangeRecord): TaskId {
return `${PendingTaskType.ExchangeCheckRefresh}:${exch.baseUrl}` as TaskId;
}
export function forTipPickup(tipRecord: TipRecord): TaskId {
return `${PendingTaskType.TipPickup}:${tipRecord.walletTipId}` as TaskId;
export function forTipPickup(tipRecord: RewardRecord): TaskId {
return `${PendingTaskType.RewardPickup}:${tipRecord.walletRewardId}` as TaskId;
}
export function forRefresh(refreshGroupRecord: RefreshGroupRecord): TaskId {
return `${PendingTaskType.Refresh}:${refreshGroupRecord.refreshGroupId}` as TaskId;

View File

@ -32,7 +32,7 @@ import {
PeerPushPaymentIncomingStatus,
PeerPullPaymentInitiationStatus,
WithdrawalGroupStatus,
TipRecordStatus,
RewardRecordStatus,
DepositOperationStatus,
} from "../db.js";
import {
@ -232,17 +232,17 @@ async function gatherDepositPending(
async function gatherTipPending(
ws: InternalWalletState,
tx: GetReadOnlyAccess<{
tips: typeof WalletStoresV1.tips;
rewards: typeof WalletStoresV1.rewards;
operationRetries: typeof WalletStoresV1.operationRetries;
}>,
now: AbsoluteTime,
resp: PendingOperationsResponse,
): Promise<void> {
const range = GlobalIDB.KeyRange.bound(
TipRecordStatus.PendingPickup,
TipRecordStatus.PendingPickup,
RewardRecordStatus.PendingPickup,
RewardRecordStatus.PendingPickup,
);
await tx.tips.indexes.byStatus.iter(range).forEachAsync(async (tip) => {
await tx.rewards.indexes.byStatus.iter(range).forEachAsync(async (tip) => {
// FIXME: The tip record needs a proper status field!
if (tip.pickedUpTimestamp) {
return;
@ -252,13 +252,13 @@ async function gatherTipPending(
const timestampDue = retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now();
if (tip.acceptedTimestamp) {
resp.pendingOperations.push({
type: PendingTaskType.TipPickup,
type: PendingTaskType.RewardPickup,
...getPendingCommon(ws, opId, timestampDue),
givesLifeness: true,
timestampDue: retryRecord?.retryInfo.nextRetry ?? AbsoluteTime.now(),
merchantBaseUrl: tip.merchantBaseUrl,
tipId: tip.walletTipId,
merchantTipId: tip.merchantTipId,
tipId: tip.walletRewardId,
merchantTipId: tip.merchantRewardId,
});
}
});
@ -494,7 +494,7 @@ export async function getPendingOperations(
x.refreshGroups,
x.coins,
x.withdrawalGroups,
x.tips,
x.rewards,
x.purchases,
x.planchets,
x.depositGroups,

View File

@ -82,7 +82,7 @@ async function putGroupAsFinished(
await tx.recoupGroups.put(recoupGroup);
}
async function recoupTipCoin(
async function recoupRewardCoin(
ws: InternalWalletState,
recoupGroupId: string,
coinIdx: number,
@ -482,8 +482,8 @@ async function processRecoup(
const cs = coin.coinSource;
switch (cs.type) {
case CoinSourceType.Tip:
return recoupTipCoin(ws, recoupGroupId, coinIdx, coin);
case CoinSourceType.Reward:
return recoupRewardCoin(ws, recoupGroupId, coinIdx, coin);
case CoinSourceType.Refresh:
return recoupRefreshCoin(ws, recoupGroupId, coinIdx, coin, cs);
case CoinSourceType.Withdraw:

View File

@ -48,8 +48,8 @@ import {
CoinRecord,
CoinSourceType,
DenominationRecord,
TipRecord,
TipRecordStatus,
RewardRecord,
RewardRecordStatus,
} from "../db.js";
import { makeErrorDetail } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
@ -84,31 +84,31 @@ const logger = new Logger("operations/tip.ts");
/**
* Get the (DD37-style) transaction status based on the
* database record of a tip.
* database record of a reward.
*/
export function computeTipTransactionStatus(
tipRecord: TipRecord,
export function computeRewardTransactionStatus(
tipRecord: RewardRecord,
): TransactionState {
switch (tipRecord.status) {
case TipRecordStatus.Done:
case RewardRecordStatus.Done:
return {
major: TransactionMajorState.Done,
};
case TipRecordStatus.Aborted:
case RewardRecordStatus.Aborted:
return {
major: TransactionMajorState.Aborted,
};
case TipRecordStatus.PendingPickup:
case RewardRecordStatus.PendingPickup:
return {
major: TransactionMajorState.Pending,
minor: TransactionMinorState.Pickup,
};
case TipRecordStatus.DialogAccept:
case RewardRecordStatus.DialogAccept:
return {
major: TransactionMajorState.Dialog,
minor: TransactionMinorState.Proposed,
};
case TipRecordStatus.SuspendidPickup:
case RewardRecordStatus.SuspendidPickup:
return {
major: TransactionMajorState.Pending,
minor: TransactionMinorState.Pickup,
@ -119,18 +119,18 @@ export function computeTipTransactionStatus(
}
export function computeTipTransactionActions(
tipRecord: TipRecord,
tipRecord: RewardRecord,
): TransactionAction[] {
switch (tipRecord.status) {
case TipRecordStatus.Done:
case RewardRecordStatus.Done:
return [TransactionAction.Delete];
case TipRecordStatus.Aborted:
case RewardRecordStatus.Aborted:
return [TransactionAction.Delete];
case TipRecordStatus.PendingPickup:
case RewardRecordStatus.PendingPickup:
return [TransactionAction.Suspend, TransactionAction.Fail];
case TipRecordStatus.SuspendidPickup:
case RewardRecordStatus.SuspendidPickup:
return [TransactionAction.Resume, TransactionAction.Fail];
case TipRecordStatus.DialogAccept:
case RewardRecordStatus.DialogAccept:
return [TransactionAction.Abort];
default:
assertUnreachable(tipRecord.status);
@ -147,9 +147,9 @@ export async function prepareTip(
}
let tipRecord = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadOnly(async (tx) => {
return tx.tips.indexes.byMerchantTipIdAndBaseUrl.get([
return tx.rewards.indexes.byMerchantTipIdAndBaseUrl.get([
res.merchantTipId,
res.merchantBaseUrl,
]);
@ -194,44 +194,44 @@ export async function prepareTip(
const secretSeed = encodeCrock(getRandomBytes(64));
const denomSelUid = encodeCrock(getRandomBytes(32));
const newTipRecord: TipRecord = {
walletTipId: walletTipId,
const newTipRecord: RewardRecord = {
walletRewardId: walletTipId,
acceptedTimestamp: undefined,
status: TipRecordStatus.DialogAccept,
tipAmountRaw: Amounts.stringify(amount),
tipExpiration: tipPickupStatus.expiration,
status: RewardRecordStatus.DialogAccept,
rewardAmountRaw: Amounts.stringify(amount),
rewardExpiration: tipPickupStatus.expiration,
exchangeBaseUrl: tipPickupStatus.exchange_url,
next_url: tipPickupStatus.next_url,
merchantBaseUrl: res.merchantBaseUrl,
createdTimestamp: TalerPreciseTimestamp.now(),
merchantTipId: res.merchantTipId,
tipAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue),
merchantRewardId: res.merchantTipId,
rewardAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue),
denomsSel: selectedDenoms,
pickedUpTimestamp: undefined,
secretSeed,
denomSelUid,
};
await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadWrite(async (tx) => {
await tx.tips.put(newTipRecord);
await tx.rewards.put(newTipRecord);
});
tipRecord = newTipRecord;
}
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId: tipRecord.walletTipId,
tag: TransactionType.Reward,
walletRewardId: tipRecord.walletRewardId,
});
const tipStatus: PrepareTipResult = {
accepted: !!tipRecord && !!tipRecord.acceptedTimestamp,
tipAmountRaw: Amounts.stringify(tipRecord.tipAmountRaw),
rewardAmountRaw: Amounts.stringify(tipRecord.rewardAmountRaw),
exchangeBaseUrl: tipRecord.exchangeBaseUrl,
merchantBaseUrl: tipRecord.merchantBaseUrl,
expirationTimestamp: tipRecord.tipExpiration,
tipAmountEffective: Amounts.stringify(tipRecord.tipAmountEffective),
walletTipId: tipRecord.walletTipId,
expirationTimestamp: tipRecord.rewardExpiration,
rewardAmountEffective: Amounts.stringify(tipRecord.rewardAmountEffective),
walletRewardId: tipRecord.walletRewardId,
transactionId,
};
@ -243,25 +243,25 @@ export async function processTip(
walletTipId: string,
): Promise<TaskRunResult> {
const tipRecord = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadOnly(async (tx) => {
return tx.tips.get(walletTipId);
return tx.rewards.get(walletTipId);
});
if (!tipRecord) {
return TaskRunResult.finished();
}
switch (tipRecord.status) {
case TipRecordStatus.Aborted:
case TipRecordStatus.DialogAccept:
case TipRecordStatus.Done:
case TipRecordStatus.SuspendidPickup:
case RewardRecordStatus.Aborted:
case RewardRecordStatus.DialogAccept:
case RewardRecordStatus.Done:
case RewardRecordStatus.SuspendidPickup:
return TaskRunResult.finished();
}
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletTipId,
});
const denomsForWithdraw = tipRecord.denomsSel;
@ -300,7 +300,7 @@ export async function processTip(
}
const tipStatusUrl = new URL(
`tips/${tipRecord.merchantTipId}/pickup`,
`tips/${tipRecord.merchantRewardId}/pickup`,
tipRecord.merchantBaseUrl,
);
@ -384,9 +384,9 @@ export async function processTip(
coinPriv: planchet.coinPriv,
coinPub: planchet.coinPub,
coinSource: {
type: CoinSourceType.Tip,
type: CoinSourceType.Reward,
coinIndex: i,
walletTipId: walletTipId,
walletRewardId: walletTipId,
},
sourceTransactionId: transactionId,
denomPubHash: denom.denomPubHash,
@ -401,20 +401,20 @@ export async function processTip(
}
const transitionInfo = await ws.db
.mktx((x) => [x.coins, x.coinAvailability, x.denominations, x.tips])
.mktx((x) => [x.coins, x.coinAvailability, x.denominations, x.rewards])
.runReadWrite(async (tx) => {
const tr = await tx.tips.get(walletTipId);
const tr = await tx.rewards.get(walletTipId);
if (!tr) {
return;
}
if (tr.status !== TipRecordStatus.PendingPickup) {
if (tr.status !== RewardRecordStatus.PendingPickup) {
return;
}
const oldTxState = computeTipTransactionStatus(tr);
const oldTxState = computeRewardTransactionStatus(tr);
tr.pickedUpTimestamp = TalerPreciseTimestamp.now();
tr.status = TipRecordStatus.Done;
await tx.tips.put(tr);
const newTxState = computeTipTransactionStatus(tr);
tr.status = RewardRecordStatus.Done;
await tx.rewards.put(tr);
const newTxState = computeRewardTransactionStatus(tr);
for (const cr of newCoinRecords) {
await makeCoinAvailable(ws, tx, cr);
}
@ -432,26 +432,26 @@ export async function acceptTip(
walletTipId: string,
): Promise<AcceptTipResponse> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletTipId,
});
const dbRes = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadWrite(async (tx) => {
const tipRecord = await tx.tips.get(walletTipId);
const tipRecord = await tx.rewards.get(walletTipId);
if (!tipRecord) {
logger.error("tip not found");
return;
}
if (tipRecord.status != TipRecordStatus.DialogAccept) {
if (tipRecord.status != RewardRecordStatus.DialogAccept) {
logger.warn("Unable to accept tip in the current state");
return { tipRecord };
}
const oldTxState = computeTipTransactionStatus(tipRecord);
const oldTxState = computeRewardTransactionStatus(tipRecord);
tipRecord.acceptedTimestamp = TalerPreciseTimestamp.now();
tipRecord.status = TipRecordStatus.PendingPickup;
await tx.tips.put(tipRecord);
const newTxState = computeTipTransactionStatus(tipRecord);
tipRecord.status = RewardRecordStatus.PendingPickup;
await tx.rewards.put(tipRecord);
const newTxState = computeRewardTransactionStatus(tipRecord);
return { tipRecord, transitionInfo: { oldTxState, newTxState } };
});
@ -465,53 +465,53 @@ export async function acceptTip(
return {
transactionId: constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId: walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletTipId,
}),
next_url: tipRecord.next_url,
};
}
export async function suspendTipTransaction(
export async function suspendRewardTransaction(
ws: InternalWalletState,
walletTipId: string,
walletRewardId: string,
): Promise<void> {
const taskId = constructTaskIdentifier({
tag: PendingTaskType.TipPickup,
walletTipId,
tag: PendingTaskType.RewardPickup,
walletRewardId: walletRewardId,
});
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletRewardId,
});
stopLongpolling(ws, taskId);
const transitionInfo = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadWrite(async (tx) => {
const tipRec = await tx.tips.get(walletTipId);
const tipRec = await tx.rewards.get(walletRewardId);
if (!tipRec) {
logger.warn(`transaction tip ${walletTipId} not found`);
logger.warn(`transaction tip ${walletRewardId} not found`);
return;
}
let newStatus: TipRecordStatus | undefined = undefined;
let newStatus: RewardRecordStatus | undefined = undefined;
switch (tipRec.status) {
case TipRecordStatus.Done:
case TipRecordStatus.SuspendidPickup:
case TipRecordStatus.Aborted:
case TipRecordStatus.DialogAccept:
case RewardRecordStatus.Done:
case RewardRecordStatus.SuspendidPickup:
case RewardRecordStatus.Aborted:
case RewardRecordStatus.DialogAccept:
break;
case TipRecordStatus.PendingPickup:
newStatus = TipRecordStatus.SuspendidPickup;
case RewardRecordStatus.PendingPickup:
newStatus = RewardRecordStatus.SuspendidPickup;
break;
default:
assertUnreachable(tipRec.status);
}
if (newStatus != null) {
const oldTxState = computeTipTransactionStatus(tipRec);
const oldTxState = computeRewardTransactionStatus(tipRec);
tipRec.status = newStatus;
const newTxState = computeTipTransactionStatus(tipRec);
await tx.tips.put(tipRec);
const newTxState = computeRewardTransactionStatus(tipRec);
await tx.rewards.put(tipRec);
return {
oldTxState,
newTxState,
@ -525,43 +525,43 @@ export async function suspendTipTransaction(
export async function resumeTipTransaction(
ws: InternalWalletState,
walletTipId: string,
walletRewardId: string,
): Promise<void> {
const taskId = constructTaskIdentifier({
tag: PendingTaskType.TipPickup,
walletTipId,
tag: PendingTaskType.RewardPickup,
walletRewardId: walletRewardId,
});
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletRewardId,
});
stopLongpolling(ws, taskId);
const transitionInfo = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadWrite(async (tx) => {
const tipRec = await tx.tips.get(walletTipId);
if (!tipRec) {
logger.warn(`transaction tip ${walletTipId} not found`);
const rewardRec = await tx.rewards.get(walletRewardId);
if (!rewardRec) {
logger.warn(`transaction reward ${walletRewardId} not found`);
return;
}
let newStatus: TipRecordStatus | undefined = undefined;
switch (tipRec.status) {
case TipRecordStatus.Done:
case TipRecordStatus.PendingPickup:
case TipRecordStatus.Aborted:
case TipRecordStatus.DialogAccept:
let newStatus: RewardRecordStatus | undefined = undefined;
switch (rewardRec.status) {
case RewardRecordStatus.Done:
case RewardRecordStatus.PendingPickup:
case RewardRecordStatus.Aborted:
case RewardRecordStatus.DialogAccept:
break;
case TipRecordStatus.SuspendidPickup:
newStatus = TipRecordStatus.PendingPickup;
case RewardRecordStatus.SuspendidPickup:
newStatus = RewardRecordStatus.PendingPickup;
break;
default:
assertUnreachable(tipRec.status);
assertUnreachable(rewardRec.status);
}
if (newStatus != null) {
const oldTxState = computeTipTransactionStatus(tipRec);
tipRec.status = newStatus;
const newTxState = computeTipTransactionStatus(tipRec);
await tx.tips.put(tipRec);
const oldTxState = computeRewardTransactionStatus(rewardRec);
rewardRec.status = newStatus;
const newTxState = computeRewardTransactionStatus(rewardRec);
await tx.rewards.put(rewardRec);
return {
oldTxState,
newTxState,
@ -582,43 +582,43 @@ export async function failTipTransaction(
export async function abortTipTransaction(
ws: InternalWalletState,
walletTipId: string,
walletRewardId: string,
): Promise<void> {
const taskId = constructTaskIdentifier({
tag: PendingTaskType.TipPickup,
walletTipId,
tag: PendingTaskType.RewardPickup,
walletRewardId: walletRewardId,
});
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId,
tag: TransactionType.Reward,
walletRewardId: walletRewardId,
});
stopLongpolling(ws, taskId);
const transitionInfo = await ws.db
.mktx((x) => [x.tips])
.mktx((x) => [x.rewards])
.runReadWrite(async (tx) => {
const tipRec = await tx.tips.get(walletTipId);
const tipRec = await tx.rewards.get(walletRewardId);
if (!tipRec) {
logger.warn(`transaction tip ${walletTipId} not found`);
logger.warn(`transaction tip ${walletRewardId} not found`);
return;
}
let newStatus: TipRecordStatus | undefined = undefined;
let newStatus: RewardRecordStatus | undefined = undefined;
switch (tipRec.status) {
case TipRecordStatus.Done:
case TipRecordStatus.Aborted:
case TipRecordStatus.PendingPickup:
case TipRecordStatus.DialogAccept:
case RewardRecordStatus.Done:
case RewardRecordStatus.Aborted:
case RewardRecordStatus.PendingPickup:
case RewardRecordStatus.DialogAccept:
break;
case TipRecordStatus.SuspendidPickup:
newStatus = TipRecordStatus.Aborted;
case RewardRecordStatus.SuspendidPickup:
newStatus = RewardRecordStatus.Aborted;
break;
default:
assertUnreachable(tipRec.status);
}
if (newStatus != null) {
const oldTxState = computeTipTransactionStatus(tipRec);
const oldTxState = computeRewardTransactionStatus(tipRec);
tipRec.status = newStatus;
const newTxState = computeTipTransactionStatus(tipRec);
await tx.tips.put(tipRec);
const newTxState = computeRewardTransactionStatus(tipRec);
await tx.rewards.put(tipRec);
return {
oldTxState,
newTxState,

View File

@ -58,7 +58,7 @@ import {
RefreshGroupRecord,
RefreshOperationStatus,
RefundGroupRecord,
TipRecord,
RewardRecord,
WalletContractData,
WithdrawalGroupRecord,
WithdrawalGroupStatus,
@ -107,11 +107,11 @@ import {
import {
abortTipTransaction,
failTipTransaction,
computeTipTransactionStatus,
computeRewardTransactionStatus,
resumeTipTransaction,
suspendTipTransaction,
suspendRewardTransaction,
computeTipTransactionActions,
} from "./tip.js";
} from "./reward.js";
import {
abortWithdrawalTransaction,
augmentPaytoUrisForWithdrawal,
@ -187,7 +187,7 @@ function shouldSkipSearch(
*/
const txOrder: { [t in TransactionType]: number } = {
[TransactionType.Withdrawal]: 1,
[TransactionType.Tip]: 2,
[TransactionType.Reward]: 2,
[TransactionType.Payment]: 3,
[TransactionType.PeerPullCredit]: 4,
[TransactionType.PeerPullDebit]: 5,
@ -284,12 +284,12 @@ export async function getTransactionById(
throw Error(`no tx for refresh`);
}
case TransactionType.Tip: {
const tipId = parsedTx.walletTipId;
case TransactionType.Reward: {
const tipId = parsedTx.walletRewardId;
return await ws.db
.mktx((x) => [x.tips, x.operationRetries])
.mktx((x) => [x.rewards, x.operationRetries])
.runReadWrite(async (tx) => {
const tipRecord = await tx.tips.get(tipId);
const tipRecord = await tx.rewards.get(tipId);
if (!tipRecord) throw Error("not found");
const retries = await tx.operationRetries.get(
@ -818,21 +818,21 @@ function buildTransactionForDeposit(
}
function buildTransactionForTip(
tipRecord: TipRecord,
tipRecord: RewardRecord,
ort?: OperationRetryRecord,
): Transaction {
checkLogicInvariant(!!tipRecord.acceptedTimestamp);
return {
type: TransactionType.Tip,
txState: computeTipTransactionStatus(tipRecord),
type: TransactionType.Reward,
txState: computeRewardTransactionStatus(tipRecord),
txActions: computeTipTransactionActions(tipRecord),
amountEffective: Amounts.stringify(tipRecord.tipAmountEffective),
amountRaw: Amounts.stringify(tipRecord.tipAmountRaw),
amountEffective: Amounts.stringify(tipRecord.rewardAmountEffective),
amountRaw: Amounts.stringify(tipRecord.rewardAmountRaw),
timestamp: tipRecord.acceptedTimestamp,
transactionId: constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId: tipRecord.walletTipId,
tag: TransactionType.Reward,
walletRewardId: tipRecord.walletRewardId,
}),
merchantBaseUrl: tipRecord.merchantBaseUrl,
...(ort?.lastError ? { error: ort.lastError } : {}),
@ -945,7 +945,7 @@ export async function getTransactions(
x.purchases,
x.contractTerms,
x.recoupGroups,
x.tips,
x.rewards,
x.tombstones,
x.withdrawalGroups,
x.refreshGroups,
@ -1200,11 +1200,11 @@ export async function getTransactions(
);
});
tx.tips.iter().forEachAsync(async (tipRecord) => {
tx.rewards.iter().forEachAsync(async (tipRecord) => {
if (
shouldSkipCurrency(
transactionsRequest,
Amounts.parseOrThrow(tipRecord.tipAmountRaw).currency,
Amounts.parseOrThrow(tipRecord.rewardAmountRaw).currency,
)
) {
return;
@ -1267,7 +1267,7 @@ export type ParsedTransactionIdentifier =
| { tag: TransactionType.PeerPushDebit; pursePub: string }
| { tag: TransactionType.Refresh; refreshGroupId: string }
| { tag: TransactionType.Refund; refundGroupId: string }
| { tag: TransactionType.Tip; walletTipId: string }
| { tag: TransactionType.Reward; walletRewardId: string }
| { tag: TransactionType.Withdrawal; withdrawalGroupId: string }
| { tag: TransactionType.InternalWithdrawal; withdrawalGroupId: string };
@ -1291,8 +1291,8 @@ export function constructTransactionIdentifier(
return `txn:${pTxId.tag}:${pTxId.refreshGroupId}` as TransactionIdStr;
case TransactionType.Refund:
return `txn:${pTxId.tag}:${pTxId.refundGroupId}` as TransactionIdStr;
case TransactionType.Tip:
return `txn:${pTxId.tag}:${pTxId.walletTipId}` as TransactionIdStr;
case TransactionType.Reward:
return `txn:${pTxId.tag}:${pTxId.walletRewardId}` as TransactionIdStr;
case TransactionType.Withdrawal:
return `txn:${pTxId.tag}:${pTxId.withdrawalGroupId}` as TransactionIdStr;
case TransactionType.InternalWithdrawal:
@ -1346,10 +1346,10 @@ export function parseTransactionIdentifier(
tag: TransactionType.Refund,
refundGroupId: rest[0],
};
case TransactionType.Tip:
case TransactionType.Reward:
return {
tag: TransactionType.Tip,
walletTipId: rest[0],
tag: TransactionType.Reward,
walletRewardId: rest[0],
};
case TransactionType.Withdrawal:
return {
@ -1427,10 +1427,10 @@ export async function retryTransaction(
stopLongpolling(ws, taskId);
break;
}
case TransactionType.Tip: {
case TransactionType.Reward: {
const taskId = constructTaskIdentifier({
tag: PendingTaskType.TipPickup,
walletTipId: parsedTx.walletTipId,
tag: PendingTaskType.RewardPickup,
walletRewardId: parsedTx.walletRewardId,
});
await resetPendingTaskTimeout(ws, taskId);
stopLongpolling(ws, taskId);
@ -1522,8 +1522,8 @@ export async function suspendTransaction(
break;
case TransactionType.Refund:
throw Error("refund transactions can't be suspended or resumed");
case TransactionType.Tip:
await suspendTipTransaction(ws, tx.walletTipId);
case TransactionType.Reward:
await suspendRewardTransaction(ws, tx.walletRewardId);
break;
default:
assertUnreachable(tx);
@ -1551,8 +1551,8 @@ export async function failTransaction(
return;
case TransactionType.Refund:
throw Error("can't do cancel-aborting on refund transaction");
case TransactionType.Tip:
await failTipTransaction(ws, tx.walletTipId);
case TransactionType.Reward:
await failTipTransaction(ws, tx.walletRewardId);
return;
case TransactionType.Refresh:
await failRefreshGroup(ws, tx.refreshGroupId);
@ -1613,8 +1613,8 @@ export async function resumeTransaction(
break;
case TransactionType.Refund:
throw Error("refund transactions can't be suspended or resumed");
case TransactionType.Tip:
await resumeTipTransaction(ws, tx.walletTipId);
case TransactionType.Reward:
await resumeTipTransaction(ws, tx.walletRewardId);
break;
}
}
@ -1763,16 +1763,16 @@ export async function deleteTransaction(
return;
}
case TransactionType.Tip: {
const tipId = parsedTx.walletTipId;
case TransactionType.Reward: {
const tipId = parsedTx.walletRewardId;
await ws.db
.mktx((x) => [x.tips, x.tombstones])
.mktx((x) => [x.rewards, x.tombstones])
.runReadWrite(async (tx) => {
const tipRecord = await tx.tips.get(tipId);
const tipRecord = await tx.rewards.get(tipId);
if (tipRecord) {
await tx.tips.delete(tipId);
await tx.rewards.delete(tipId);
await tx.tombstones.put({
id: TombstoneTag.DeleteTip + ":" + tipId,
id: TombstoneTag.DeleteReward + ":" + tipId,
});
}
});
@ -1856,8 +1856,8 @@ export async function abortTransaction(
case TransactionType.Deposit:
await abortDepositGroup(ws, txId.depositGroupId);
break;
case TransactionType.Tip:
await abortTipTransaction(ws, txId.walletTipId);
case TransactionType.Reward:
await abortTipTransaction(ws, txId.walletRewardId);
break;
case TransactionType.Refund:
throw Error("can't abort refund transactions");

View File

@ -33,7 +33,7 @@ export enum PendingTaskType {
Purchase = "purchase",
Refresh = "refresh",
Recoup = "recoup",
TipPickup = "tip-pickup",
RewardPickup = "reward-pickup",
Withdraw = "withdraw",
Deposit = "deposit",
Backup = "backup",
@ -144,7 +144,7 @@ export interface PendingRefreshTask {
* The wallet is picking up a tip that the user has accepted.
*/
export interface PendingTipPickupTask {
type: PendingTaskType.TipPickup;
type: PendingTaskType.RewardPickup;
tipId: string;
merchantBaseUrl: string;
merchantTipId: string;

View File

@ -29,7 +29,7 @@ import {
AcceptExchangeTosRequest,
AcceptManualWithdrawalRequest,
AcceptManualWithdrawalResult,
AcceptTipRequest,
AcceptRewardRequest,
AcceptTipResponse,
AcceptWithdrawalResponse,
AddExchangeRequest,
@ -85,8 +85,8 @@ import {
PreparePeerPushCreditRequest,
PreparePeerPushCreditResponse,
PrepareRefundRequest,
PrepareTipRequest,
PrepareTipResult,
PrepareRewardRequest as PrepareRewardRequest,
PrepareTipResult as PrepareRewardResult,
RecoveryLoadRequest,
RetryTransactionRequest,
SetCoinSuspendedRequest,
@ -178,8 +178,8 @@ export enum WalletApiOperation {
DumpCoins = "dumpCoins",
SetCoinSuspended = "setCoinSuspended",
ForceRefresh = "forceRefresh",
PrepareTip = "prepareTip",
AcceptTip = "acceptTip",
PrepareReward = "prepareReward",
AcceptReward = "acceptReward",
ExportBackup = "exportBackup",
AddBackupProvider = "addBackupProvider",
RemoveBackupProvider = "removeBackupProvider",
@ -507,23 +507,23 @@ export type StartRefundQueryOp = {
response: EmptyObject;
};
// group: Tipping
// group: Rewards
/**
* Query and store information about a tip.
* Query and store information about a reward.
*/
export type PrepareTipOp = {
op: WalletApiOperation.PrepareTip;
request: PrepareTipRequest;
response: PrepareTipResult;
op: WalletApiOperation.PrepareReward;
request: PrepareRewardRequest;
response: PrepareRewardResult;
};
/**
* Accept a tip.
* Accept a reward.
*/
export type AcceptTipOp = {
op: WalletApiOperation.AcceptTip;
request: AcceptTipRequest;
op: WalletApiOperation.AcceptReward;
request: AcceptRewardRequest;
response: AcceptTipResponse;
};
@ -1023,8 +1023,8 @@ export type WalletOperations = {
[WalletApiOperation.ForceRefresh]: ForceRefreshOp;
[WalletApiOperation.DeleteTransaction]: DeleteTransactionOp;
[WalletApiOperation.RetryTransaction]: RetryTransactionOp;
[WalletApiOperation.PrepareTip]: PrepareTipOp;
[WalletApiOperation.AcceptTip]: AcceptTipOp;
[WalletApiOperation.PrepareReward]: PrepareTipOp;
[WalletApiOperation.AcceptReward]: AcceptTipOp;
[WalletApiOperation.StartRefundQueryForUri]: StartRefundQueryForUriOp;
[WalletApiOperation.StartRefundQuery]: StartRefundQueryOp;
[WalletApiOperation.ListCurrencies]: ListCurrenciesOp;

View File

@ -93,7 +93,7 @@ import {
codecForPreparePeerPullPaymentRequest,
codecForPreparePeerPushCreditRequest,
codecForPrepareRefundRequest,
codecForPrepareTipRequest,
codecForPrepareRewardRequest,
codecForResumeTransaction,
codecForRetryTransactionRequest,
codecForSetCoinSuspendedRequest,
@ -249,10 +249,10 @@ import {
} from "./operations/testing.js";
import {
acceptTip,
computeTipTransactionStatus,
computeRewardTransactionStatus,
prepareTip,
processTip,
} from "./operations/tip.js";
} from "./operations/reward.js";
import {
abortTransaction,
deleteTransaction,
@ -329,7 +329,7 @@ async function callOperationHandler(
return await processRefreshGroup(ws, pending.refreshGroupId);
case PendingTaskType.Withdraw:
return await processWithdrawalGroup(ws, pending.withdrawalGroupId);
case PendingTaskType.TipPickup:
case PendingTaskType.RewardPickup:
return await processTip(ws, pending.tipId);
case PendingTaskType.Purchase:
return await processPurchase(ws, pending.proposalId);
@ -1350,9 +1350,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
refreshGroupId,
};
}
case WalletApiOperation.PrepareTip: {
const req = codecForPrepareTipRequest().decode(payload);
return await prepareTip(ws, req.talerTipUri);
case WalletApiOperation.PrepareReward: {
const req = codecForPrepareRewardRequest().decode(payload);
return await prepareTip(ws, req.talerRewardUri);
}
case WalletApiOperation.StartRefundQueryForUri: {
const req = codecForPrepareRefundRequest().decode(payload);
@ -1370,9 +1370,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
await startQueryRefund(ws, txIdParsed.proposalId);
return {};
}
case WalletApiOperation.AcceptTip: {
case WalletApiOperation.AcceptReward: {
const req = codecForAcceptTipRequest().decode(payload);
return await acceptTip(ws, req.walletTipId);
return await acceptTip(ws, req.walletRewardId);
}
case WalletApiOperation.ExportBackupPlain: {
return exportBackup(ws);
@ -1884,12 +1884,12 @@ class InternalWalletStateImpl implements InternalWalletState {
}
return computeRefreshTransactionState(rec);
}
case TransactionType.Tip: {
const rec = await tx.tips.get(parsedTxId.walletTipId);
case TransactionType.Reward: {
const rec = await tx.rewards.get(parsedTxId.walletRewardId);
if (!rec) {
return undefined;
}
return computeTipTransactionStatus(rec);
return computeRewardTransactionStatus(rec);
}
default:
assertUnreachable(parsedTxId);

View File

@ -134,7 +134,7 @@ export function HistoryItem(props: { tx: Transaction }): VNode {
}
/>
);
case TransactionType.Tip:
case TransactionType.Reward:
return (
<Layout
id={tx.transactionId}

View File

@ -23,7 +23,7 @@ import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { Props, State } from "./index.js";
export function useComponentState({
talerTipUri,
talerTipUri: talerRewardUri,
onCancel,
onSuccess,
}: Props): State {
@ -31,9 +31,9 @@ export function useComponentState({
const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext();
const tipInfo = useAsyncAsHook(async () => {
if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
const tip = await api.wallet.call(WalletApiOperation.PrepareTip, {
talerTipUri,
if (!talerRewardUri) throw Error("ERROR_NO-URI-FOR-TIP");
const tip = await api.wallet.call(WalletApiOperation.PrepareReward, {
talerRewardUri,
});
return { tip };
});
@ -63,8 +63,8 @@ export function useComponentState({
const { tip } = tipInfo.response;
const doAccept = async (): Promise<void> => {
const res = await api.wallet.call(WalletApiOperation.AcceptTip, {
walletTipId: tip.walletTipId,
const res = await api.wallet.call(WalletApiOperation.AcceptReward, {
walletRewardId: tip.walletRewardId,
});
//FIX: this may not be seen since we are moving to the success also
@ -75,7 +75,7 @@ export function useComponentState({
const baseInfo = {
merchantBaseUrl: tip.merchantBaseUrl,
exchangeBaseUrl: tip.exchangeBaseUrl,
amount: Amounts.parseOrThrow(tip.tipAmountEffective),
amount: Amounts.parseOrThrow(tip.rewardAmountEffective),
error: undefined,
cancel: {
onClick: pushAlertOnError(onCancel),

View File

@ -62,17 +62,17 @@ describe("Tip CTA states", () => {
it("should be ready for accepting the tip", async () => {
const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
handler.addWalletCallResponse(WalletApiOperation.PrepareReward, undefined, {
accepted: false,
exchangeBaseUrl: "exchange url",
merchantBaseUrl: "merchant url",
tipAmountEffective: "EUR:1",
walletTipId: "tip_id",
rewardAmountEffective: "EUR:1",
walletRewardId: "tip_id",
transactionId: "txn:tip:ABC1234",
expirationTimestamp: {
t_s: 1,
},
tipAmountRaw: "",
rewardAmountRaw: "",
});
const props: Props = {
@ -100,23 +100,23 @@ describe("Tip CTA states", () => {
expect(state.exchangeBaseUrl).eq("exchange url");
if (state.accept.onClick === undefined) expect.fail();
handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
handler.addWalletCallResponse(WalletApiOperation.AcceptReward);
state.accept.onClick();
handler.addWalletCallResponse(
WalletApiOperation.PrepareTip,
WalletApiOperation.PrepareReward,
undefined,
{
accepted: true,
exchangeBaseUrl: "exchange url",
merchantBaseUrl: "merchant url",
tipAmountEffective: "EUR:1",
walletTipId: "tip_id",
rewardAmountEffective: "EUR:1",
walletRewardId: "tip_id",
transactionId: "txn:tip:ABC1234",
expirationTimestamp: {
t_s: 1,
},
tipAmountRaw: "",
rewardAmountRaw: "",
},
);
},
@ -137,17 +137,17 @@ describe("Tip CTA states", () => {
it.skip("should be ignored after clicking the ignore button", async () => {
const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
handler.addWalletCallResponse(WalletApiOperation.PrepareReward, undefined, {
exchangeBaseUrl: "exchange url",
merchantBaseUrl: "merchant url",
tipAmountEffective: "EUR:1",
walletTipId: "tip_id",
rewardAmountEffective: "EUR:1",
walletRewardId: "tip_id",
transactionId: "txn:tip:ABC1234",
accepted: false,
expirationTimestamp: {
t_s: 1,
},
tipAmountRaw: "",
rewardAmountRaw: "",
});
const props: Props = {
@ -184,17 +184,17 @@ describe("Tip CTA states", () => {
it("should render accepted if the tip has been used previously", async () => {
const { handler, TestingContext } = createWalletApiMock();
handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
handler.addWalletCallResponse(WalletApiOperation.PrepareReward, undefined, {
accepted: true,
exchangeBaseUrl: "exchange url",
merchantBaseUrl: "merchant url",
tipAmountEffective: "EUR:1",
walletTipId: "tip_id",
rewardAmountEffective: "EUR:1",
walletRewardId: "tip_id",
transactionId: "txn:tip:ABC1234",
expirationTimestamp: {
t_s: 1,
},
tipAmountRaw: "",
rewardAmountRaw: "",
});
const props: Props = {

View File

@ -22,7 +22,7 @@
export * as a1 from "./Deposit/stories.jsx";
export * as a3 from "./Payment/stories.jsx";
export * as a4 from "./Refund/stories.jsx";
export * as a5 from "./Tip/stories.jsx";
export * as a5 from "./Reward/stories.js";
export * as a6 from "./Withdraw/stories.jsx";
export * as a8 from "./InvoiceCreate/stories.js";
export * as a9 from "./InvoicePay/stories.js";

View File

@ -58,7 +58,7 @@ import { PaymentPage } from "../cta/Payment/index.js";
import { PaymentTemplatePage } from "../cta/PaymentTemplate/index.js";
import { RecoveryPage } from "../cta/Recovery/index.js";
import { RefundPage } from "../cta/Refund/index.js";
import { TipPage } from "../cta/Tip/index.js";
import { TipPage } from "../cta/Reward/index.js";
import { TransferCreatePage } from "../cta/TransferCreate/index.js";
import { TransferPickupPage } from "../cta/TransferPickup/index.js";
import {

View File

@ -34,7 +34,7 @@ import {
TransactionPeerPushDebit,
TransactionRefresh,
TransactionRefund,
TransactionTip,
TransactionReward,
TransactionType,
TransactionWithdrawal,
WithdrawalType,
@ -113,9 +113,9 @@ const exampleData = {
} as TransactionRefresh,
tip: {
...commonTransaction(),
type: TransactionType.Tip,
type: TransactionType.Reward,
merchantBaseUrl: "http://ads.merchant.taler.net/",
} as TransactionTip,
} as TransactionReward,
refund: {
...commonTransaction(),
type: TransactionType.Refund,

View File

@ -37,7 +37,7 @@ import {
TransactionPeerPushDebit,
TransactionRefresh,
TransactionRefund,
TransactionTip,
TransactionReward,
TransactionType,
TransactionWithdrawal,
WithdrawalDetails,
@ -138,7 +138,7 @@ const exampleData = {
} as TransactionRefresh,
tip: {
...commonTransaction,
type: TransactionType.Tip,
type: TransactionType.Reward,
// merchant: {
// name: "the merchant",
// logo: merchantIcon,
@ -146,7 +146,7 @@ const exampleData = {
// email: "contact@merchant.taler",
// },
merchantBaseUrl: "http://merchant.taler",
} as TransactionTip,
} as TransactionReward,
refund: {
...commonTransaction,
type: TransactionType.Refund,

View File

@ -745,7 +745,7 @@ export function TransactionView({
);
}
if (transaction.type === TransactionType.Tip) {
if (transaction.type === TransactionType.Reward) {
return (
<TransactionTemplate
transaction={transaction}