From efed6b32c5f4680f3175305985c4371517131927 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 2 Aug 2023 07:40:28 -0300 Subject: [PATCH 01/12] fix #7717 --- packages/taler-util/src/wallet-types.ts | 3 +++ packages/taler-wallet-core/.gitignore | 1 + packages/taler-wallet-core/package.json | 4 ++-- packages/taler-wallet-core/src/wallet.ts | 15 +++++---------- packages/taler-wallet-core/tsconfig.json | 7 ++++++- pnpm-lock.yaml | 2 +- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 93653240b..5151b8aae 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -994,6 +994,9 @@ export interface ExchangeDetailedResponse { } export interface WalletCoreVersion { + /** + * @deprecated + */ hash: string | undefined; version: string; exchange: string; diff --git a/packages/taler-wallet-core/.gitignore b/packages/taler-wallet-core/.gitignore index cb5a51ac5..13d7285e1 100644 --- a/packages/taler-wallet-core/.gitignore +++ b/packages/taler-wallet-core/.gitignore @@ -1,2 +1,3 @@ /lib /coverage +/src/version.json diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json index bf4efe814..90ef6a453 100644 --- a/packages/taler-wallet-core/package.json +++ b/packages/taler-wallet-core/package.json @@ -12,7 +12,7 @@ "author": "Florian Dold", "license": "GPL-3.0", "scripts": { - "compile": "tsc --build", + "compile": "jq '{version}' package.json > src/version.json && tsc --build", "pretty": "prettier --write src", "test": "tsc && ava", "coverage": "tsc && c8 --src src --all ava", @@ -85,4 +85,4 @@ "lib/**/*test.*" ] } -} \ No newline at end of file +} diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 628a55e92..1f5c6ee3b 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -310,6 +310,7 @@ import { WalletCoreApiClient, WalletCoreResponseType, } from "./wallet-api-types.js"; +import versionInfo from "./version.json" assert { type: 'json' }; const logger = new Logger("wallet.ts"); @@ -1016,12 +1017,6 @@ export async function getClientFromWalletState( return client; } -declare const __VERSION__: string; -declare const __GIT_HASH__: string; - -const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "dev"; -const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; - /** * Implementation of the "wallet-core" API. */ @@ -1590,15 +1585,15 @@ async function dispatchRequestInternal( } export function getVersion(ws: InternalWalletState): WalletCoreVersion { - const version: WalletCoreVersion = { - hash: GIT_HASH, - version: VERSION, + const result: WalletCoreVersion = { + hash: undefined, + version: versionInfo.version, exchange: WALLET_EXCHANGE_PROTOCOL_VERSION, merchant: WALLET_MERCHANT_PROTOCOL_VERSION, bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, devMode: false, }; - return version; + return result; } /** diff --git a/packages/taler-wallet-core/tsconfig.json b/packages/taler-wallet-core/tsconfig.json index 5b74121a2..8de28b3d8 100644 --- a/packages/taler-wallet-core/tsconfig.json +++ b/packages/taler-wallet-core/tsconfig.json @@ -7,8 +7,10 @@ "target": "ES2017", "module": "ESNext", "moduleResolution": "Node16", + "resolveJsonModule": true, "sourceMap": true, "lib": ["es6"], + "resolvePackageJsonImports": true, "types": ["node"], "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, @@ -31,5 +33,8 @@ "path": "../taler-util/" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*", + "src/*.json" + ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9d1a2fa3..f7fd2f134 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' settings: autoInstallPeers: true From 22a3017d52f44e140971ce3791f7d75227c07f90 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 2 Aug 2023 09:49:14 -0300 Subject: [PATCH 02/12] removing import assert since it breaks with linaria --- packages/taler-wallet-core/src/wallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 1f5c6ee3b..f8bbd21fc 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -310,7 +310,7 @@ import { WalletCoreApiClient, WalletCoreResponseType, } from "./wallet-api-types.js"; -import versionInfo from "./version.json" assert { type: 'json' }; +import versionInfo from "./version.json"; const logger = new Logger("wallet.ts"); From 60929c34f3e342a4f2b47a7e0172ada3e58d6f07 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 2 Aug 2023 10:30:40 -0300 Subject: [PATCH 03/12] use local port --- packages/web-util/src/live-reload.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/web-util/src/live-reload.ts b/packages/web-util/src/live-reload.ts index 8e5e7da71..407ef9e84 100644 --- a/packages/web-util/src/live-reload.ts +++ b/packages/web-util/src/live-reload.ts @@ -2,8 +2,7 @@ function setupLiveReload(): void { const protocol = window.location.protocol === "http:" ? "ws:" : "wss:"; - const port = window.location.protocol === "http:" ? "8080" : "8081"; - const ws = new WebSocket(`${protocol}//localhost:${port}/ws`); + const ws = new WebSocket(`${protocol}//${window.location.hostname}:${window.location.port}/ws`); ws.addEventListener("message", (message) => { try { From 72b8a70da2b49d767aa0262fe4095adf4523e469 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 2 Aug 2023 10:41:14 -0300 Subject: [PATCH 04/12] fix #7830 --- .../src/components/form/InputSelector.tsx | 12 +++++++--- .../src/declaration.d.ts | 3 ++- .../instance/webhooks/create/CreatePage.tsx | 23 ++++++++++++++++--- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/merchant-backoffice-ui/src/components/form/InputSelector.tsx b/packages/merchant-backoffice-ui/src/components/form/InputSelector.tsx index 8a57a9de8..a8dad5d89 100644 --- a/packages/merchant-backoffice-ui/src/components/form/InputSelector.tsx +++ b/packages/merchant-backoffice-ui/src/components/form/InputSelector.tsx @@ -44,7 +44,7 @@ export function InputSelector({ fromStr = defaultFromString, toStr = defaultToString, }: Props): VNode { - const { error, value, onChange } = useField(name); + const { error, value, onChange, required } = useField(name); return (
@@ -58,8 +58,8 @@ export function InputSelector({
-
-

+

+

+ {help}

+ {required && ( + + + + )} {error &&

{error}

}
diff --git a/packages/merchant-backoffice-ui/src/declaration.d.ts b/packages/merchant-backoffice-ui/src/declaration.d.ts index 8afa2f781..db3122266 100644 --- a/packages/merchant-backoffice-ui/src/declaration.d.ts +++ b/packages/merchant-backoffice-ui/src/declaration.d.ts @@ -1331,12 +1331,13 @@ export namespace MerchantBackend { } namespace Webhooks { + type MerchantWebhookType = "pay" | "refund"; interface WebhookAddDetails { // Webhook ID to use. webhook_id: string; // The event of the webhook: why the webhook is used. - event_type: string; + event_type: MerchantWebhookType; // URL of the webhook where the customer will be redirected. url: string; diff --git a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx index ed11f86a5..7b07e689e 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx @@ -33,6 +33,7 @@ import { InputDuration } from "../../../../components/form/InputDuration.js"; import { InputNumber } from "../../../../components/form/InputNumber.js"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; +import { InputSelector } from "../../../../components/form/InputSelector.js"; type Entity = MerchantBackend.Webhooks.WebhookAddDetails; @@ -50,7 +51,9 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { const errors: FormErrors = { webhook_id: !state.webhook_id ? i18n.str`required` : undefined, - event_type: !state.event_type ? i18n.str`required` : undefined, + event_type: !state.event_type ? i18n.str`required` + : state.event_type !== "pay" && state.event_type !== "refund" ? i18n.str`it should be "pay" or "refund"` + : undefined, http_method: !state.http_method ? i18n.str`required` : !validMethod.includes(state.http_method) @@ -84,16 +87,30 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { label={i18n.str`ID`} tooltip={i18n.str`Webhook ID to use`} /> - + - + + name="url" label={i18n.str`URL`} From 21f678ead97b16b4549026f354e7cb981a7f76af Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 2 Aug 2023 10:59:19 -0300 Subject: [PATCH 05/12] fix #7800 --- .../demobank-ui/src/pages/AccountPage.tsx | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/packages/demobank-ui/src/pages/AccountPage.tsx b/packages/demobank-ui/src/pages/AccountPage.tsx index edc5da5ae..820c59984 100644 --- a/packages/demobank-ui/src/pages/AccountPage.tsx +++ b/packages/demobank-ui/src/pages/AccountPage.tsx @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see */ -import { Amounts, HttpStatusCode, parsePaytoUri } from "@gnu-taler/taler-util"; +import { Amounts, HttpStatusCode, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; import { ErrorType, HttpResponsePaginated, @@ -27,6 +27,7 @@ import { useAccountDetails } from "../hooks/access.js"; import { LoginForm } from "./LoginForm.js"; import { PaymentOptions } from "./PaymentOptions.js"; import { notifyError } from "../hooks/notification.js"; +import { useEffect, useState } from "preact/hooks"; interface Props { account: string; @@ -34,6 +35,60 @@ interface Props { error: HttpResponsePaginated, ) => VNode; } + +export const CopyIcon = (): VNode => ( + + + + +); + +export const CopiedIcon = (): VNode => ( + + + +); + +function CopyButton({ getContent }: { getContent: () => string }): VNode { + const [copied, setCopied] = useState(false); + function copyText(): void { + navigator.clipboard.writeText(getContent() || ""); + setCopied(true); + } + useEffect(() => { + if (copied) { + setTimeout(() => { + setCopied(false); + }, 1000); + } + }, [copied]); + + if (!copied) { + return ( + + ); + } + return ( +
+ +
+ ); +} + + /** * Query account information and show QR code if there is pending withdrawal */ @@ -66,7 +121,6 @@ export function AccountPage({ account, onLoadNotOk }: Props): VNode {
Payto from server is not valid "{data.paytoUri}"
); } - const accountNumber = payto.iban; const balanceIsDebit = data.balance.credit_debit_indicator == "debit"; const limit = balanceIsDebit ? Amounts.sub(debitThreshold, balance).amount @@ -76,8 +130,7 @@ export function AccountPage({ account, onLoadNotOk }: Props): VNode {

- Welcome, {accountNumber ? `${account} (${accountNumber})` : account} - ! + Welcome, {account} ({payto.iban})! stringifyPaytoUri(payto)} />

From 475fdb502b30afd52fce82fb712e309565c01a0d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 2 Aug 2023 16:27:54 +0200 Subject: [PATCH 06/12] organize imports --- .../taler-wallet-core/src/crypto/cryptoImplementation.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts index 76c13bcb4..16d96eaa9 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts @@ -28,7 +28,6 @@ import { AgeCommitmentProof, AgeRestriction, AmountJson, - AmountLike, Amounts, AmountString, amountToBuffer, @@ -64,7 +63,6 @@ import { hashCoinPub, hashDenomPub, hashTruncate32, - j2s, kdf, kdfKw, keyExchangeEcdhEddsa, @@ -81,16 +79,13 @@ import { rsaVerify, setupTipPlanchet, stringToBytes, - TalerProtocolDuration, TalerProtocolTimestamp, TalerSignaturePurpose, timestampRoundedToBuffer, UnblindedSignature, - validateIban, WireFee, WithdrawalPlanchet, } from "@gnu-taler/taler-util"; -import bigint from "big-integer"; // FIXME: Crypto should not use DB Types! import { DenominationRecord } from "../db.js"; import { @@ -108,7 +103,6 @@ import { EncryptContractForDepositResponse, EncryptContractRequest, EncryptContractResponse, - EncryptedContract, SignDeletePurseRequest, SignDeletePurseResponse, SignPurseMergeRequest, From 0fe4840ca2612dda06417cdebe5229eea98180be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Thu, 3 Aug 2023 13:18:07 +0200 Subject: [PATCH 07/12] -fix Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f493c24e9..45deb0d2c 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ install: .PHONY: install-tools # Install taler-wallet-cli, anastasis-cli and taler-harness install-tools: - pnpm install --frozen-lockfile --filter @gnu-taler/taler-wallet-cli... --filder @gnu-taler/anastasis-cli... --filter @gnu-taler/taler-harness... + pnpm install --frozen-lockfile --filter @gnu-taler/taler-wallet-cli... --filter @gnu-taler/anastasis-cli... --filter @gnu-taler/taler-harness... pnpm run --filter @gnu-taler/taler-wallet-cli... --filter @gnu-taler/anastasis-cli... --filter @gnu-taler/taler-harness... compile make -C packages/taler-wallet-cli TOPLEVEL=yes install-nodeps make -C packages/anastasis-cli TOPLEVEL=yes install-nodeps From fdbd55d2bde0961a4c1ff26b04e442459ab782b0 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 3 Aug 2023 18:35:07 +0200 Subject: [PATCH 08/12] -towards tip->reward rename --- packages/taler-harness/src/harness/harness.ts | 8 +- .../test-age-restrictions-merchant.ts | 8 +- .../src/integrationtests/test-tipping.ts | 14 +- packages/taler-util/src/backup-types.ts | 4 +- packages/taler-util/src/http-impl.node.ts | 22 +- packages/taler-util/src/merchant-api-types.ts | 14 +- packages/taler-util/src/transactions-types.ts | 8 +- packages/taler-util/src/wallet-types.ts | 38 +-- packages/taler-wallet-cli/src/index.ts | 8 +- packages/taler-wallet-core/src/db.ts | 58 ++--- .../src/operations/backup/export.ts | 18 +- .../src/operations/backup/import.ts | 32 +-- .../src/operations/common.ts | 32 +-- .../src/operations/pending.ts | 18 +- .../src/operations/recoup.ts | 6 +- .../src/operations/{tip.ts => reward.ts} | 242 +++++++++--------- .../src/operations/transactions.ts | 84 +++--- .../taler-wallet-core/src/pending-types.ts | 4 +- .../taler-wallet-core/src/wallet-api-types.ts | 30 +-- packages/taler-wallet-core/src/wallet.ts | 24 +- .../src/components/HistoryItem.tsx | 2 +- .../src/cta/{Tip => Reward}/index.ts | 0 .../src/cta/{Tip => Reward}/state.ts | 14 +- .../src/cta/{Tip => Reward}/stories.tsx | 0 .../src/cta/{Tip => Reward}/test.ts | 34 +-- .../src/cta/{Tip => Reward}/views.tsx | 0 .../src/cta/index.stories.ts | 2 +- .../src/wallet/Application.tsx | 2 +- .../src/wallet/History.stories.tsx | 6 +- .../src/wallet/Transaction.stories.tsx | 6 +- .../src/wallet/Transaction.tsx | 2 +- 31 files changed, 372 insertions(+), 368 deletions(-) rename packages/taler-wallet-core/src/operations/{tip.ts => reward.ts} (72%) rename packages/taler-wallet-webextension/src/cta/{Tip => Reward}/index.ts (100%) rename packages/taler-wallet-webextension/src/cta/{Tip => Reward}/state.ts (89%) rename packages/taler-wallet-webextension/src/cta/{Tip => Reward}/stories.tsx (100%) rename packages/taler-wallet-webextension/src/cta/{Tip => Reward}/test.ts (90%) rename packages/taler-wallet-webextension/src/cta/{Tip => Reward}/views.tsx (100%) diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index 940e4258a..c9202c60e 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -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 { + req: RewardCreateRequest, + ): Promise { const reqUrl = new URL( `private/tips`, merchantService.makeInstanceBaseUrl(instance), diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts index c4db7022d..919097deb 100644 --- a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts +++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts @@ -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(); diff --git a/packages/taler-harness/src/integrationtests/test-tipping.ts b/packages/taler-harness/src/integrationtests/test-tipping.ts index ff6fc9ceb..332f702d7 100644 --- a/packages/taler-harness/src/integrationtests/test-tipping.ts +++ b/packages/taler-harness/src/integrationtests/test-tipping.ts @@ -99,17 +99,17 @@ export async function runTippingTest(t: GlobalTestState) { console.log("created tip", tip); const doTip = async (): Promise => { - 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, diff --git a/packages/taler-util/src/backup-types.ts b/packages/taler-util/src/backup-types.ts index 2920838dd..0211ff740 100644 --- a/packages/taler-util/src/backup-types.ts +++ b/packages/taler-util/src/backup-types.ts @@ -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 diff --git a/packages/taler-util/src/http-impl.node.ts b/packages/taler-util/src/http-impl.node.ts index 639043201..07648a28d 100644 --- a/packages/taler-util/src/http-impl.node.ts +++ b/packages/taler-util/src/http-impl.node.ts @@ -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) { diff --git a/packages/taler-util/src/merchant-api-types.ts b/packages/taler-util/src/merchant-api-types.ts index d7a5cf576..9f00173f2 100644 --- a/packages/taler-util/src/merchant-api-types.ts +++ b/packages/taler-util/src/merchant-api-types.ts @@ -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; diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts index a498d3471..2d278e3e8 100644 --- a/packages/taler-util/src/transactions-types.ts +++ b/packages/taler-util/src/transactions-types.ts @@ -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; diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 5151b8aae..38e5787ba 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -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 => buildCodecForObject() .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 => - buildCodecForObject() - .property("talerTipUri", codecForString()) - .build("PrepareTipRequest"); +export const codecForPrepareRewardRequest = (): Codec => + buildCodecForObject() + .property("talerRewardUri", codecForString()) + .build("PrepareRewardRequest"); -export interface AcceptTipRequest { - walletTipId: string; +export interface AcceptRewardRequest { + walletRewardId: string; } -export const codecForAcceptTipRequest = (): Codec => - buildCodecForObject() - .property("walletTipId", codecForString()) - .build("AcceptTipRequest"); +export const codecForAcceptTipRequest = (): Codec => + buildCodecForObject() + .property("walletRewardId", codecForString()) + .build("AcceptRewardRequest"); export interface FailTransactionRequest { transactionId: TransactionIdStr; diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index 4e56a40f4..a34f6be03 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -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; } diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 6a7a26f2f..3d2878d93 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -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({ keyPath: "walletTipId" }), + rewards: describeStore( + "rewards", + describeContents({ 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 { - 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 { diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index 21ba5dc37..c9446a05f 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -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: diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index b161aa8f2..a53b624e8 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -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 { diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts index cc16a4704..7a8b78b53 100644 --- a/packages/taler-wallet-core/src/operations/common.ts +++ b/packages/taler-wallet-core/src/operations/common.ts @@ -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; diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index 870437e2e..cc9217d67 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -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 { 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, diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index dea2d4b16..abeca1119 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -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: diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/reward.ts similarity index 72% rename from packages/taler-wallet-core/src/operations/tip.ts rename to packages/taler-wallet-core/src/operations/reward.ts index e56fb1e8d..58c745780 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/reward.ts @@ -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 { 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 { 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 { 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 { 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 { 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, diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 868f00de7..a16809b36 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -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"); diff --git a/packages/taler-wallet-core/src/pending-types.ts b/packages/taler-wallet-core/src/pending-types.ts index 3bb6636ee..82eb542a7 100644 --- a/packages/taler-wallet-core/src/pending-types.ts +++ b/packages/taler-wallet-core/src/pending-types.ts @@ -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; diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index e395237cf..eaa99a6c3 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -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; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index f8bbd21fc..4a83db856 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -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( 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( 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); diff --git a/packages/taler-wallet-webextension/src/components/HistoryItem.tsx b/packages/taler-wallet-webextension/src/components/HistoryItem.tsx index a0ce04460..e072d2581 100644 --- a/packages/taler-wallet-webextension/src/components/HistoryItem.tsx +++ b/packages/taler-wallet-webextension/src/components/HistoryItem.tsx @@ -134,7 +134,7 @@ export function HistoryItem(props: { tx: Transaction }): VNode { } /> ); - case TransactionType.Tip: + case TransactionType.Reward: return ( { - 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 => { - 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), diff --git a/packages/taler-wallet-webextension/src/cta/Tip/stories.tsx b/packages/taler-wallet-webextension/src/cta/Reward/stories.tsx similarity index 100% rename from packages/taler-wallet-webextension/src/cta/Tip/stories.tsx rename to packages/taler-wallet-webextension/src/cta/Reward/stories.tsx diff --git a/packages/taler-wallet-webextension/src/cta/Tip/test.ts b/packages/taler-wallet-webextension/src/cta/Reward/test.ts similarity index 90% rename from packages/taler-wallet-webextension/src/cta/Tip/test.ts rename to packages/taler-wallet-webextension/src/cta/Reward/test.ts index e0b6210a2..6d7bad0c8 100644 --- a/packages/taler-wallet-webextension/src/cta/Tip/test.ts +++ b/packages/taler-wallet-webextension/src/cta/Reward/test.ts @@ -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 = { diff --git a/packages/taler-wallet-webextension/src/cta/Tip/views.tsx b/packages/taler-wallet-webextension/src/cta/Reward/views.tsx similarity index 100% rename from packages/taler-wallet-webextension/src/cta/Tip/views.tsx rename to packages/taler-wallet-webextension/src/cta/Reward/views.tsx diff --git a/packages/taler-wallet-webextension/src/cta/index.stories.ts b/packages/taler-wallet-webextension/src/cta/index.stories.ts index 84863f84f..06b11ef6d 100644 --- a/packages/taler-wallet-webextension/src/cta/index.stories.ts +++ b/packages/taler-wallet-webextension/src/cta/index.stories.ts @@ -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"; diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx index d8cb22bf0..98515aac0 100644 --- a/packages/taler-wallet-webextension/src/wallet/Application.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx @@ -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 { diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx index 149c8c1f4..1ddb24b02 100644 --- a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx @@ -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, diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx index f2e3982f6..3ba3ac591 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx @@ -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, diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 8d564a275..e54137016 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -745,7 +745,7 @@ export function TransactionView({ ); } - if (transaction.type === TransactionType.Tip) { + if (transaction.type === TransactionType.Reward) { return ( Date: Thu, 3 Aug 2023 18:40:25 +0200 Subject: [PATCH 09/12] fix taleruri test failure --- packages/taler-util/src/taleruri.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/taler-util/src/taleruri.test.ts b/packages/taler-util/src/taleruri.test.ts index eb74436cb..3244bbbd9 100644 --- a/packages/taler-util/src/taleruri.test.ts +++ b/packages/taler-util/src/taleruri.test.ts @@ -367,6 +367,6 @@ test("taler withdraw exchange URI with amount (stringify)", (t) => { }); t.deepEqual( url, - "taler://withdraw-exchange/exchange.demo.taler.net/JFX1NE38C65A5XT8VSNQXX7R7BBG4GNZ63F5T7Y6859V4J8KBKF0?a=KUDOS%3A19", + "taler://withdraw-exchange/exchange.demo.taler.net/GJKG23V4ZBHEH45YRK7TWQE8ZTY7JWTY5094TQJSRZN5DSDBX8E0?a=KUDOS%3A19", ); }); From 0b5d0cdc71b8a6828a0ebae051c911225b354154 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 3 Aug 2023 18:58:44 +0200 Subject: [PATCH 10/12] fix version substitution --- packages/taler-wallet-core/package.json | 2 +- packages/taler-wallet-core/src/versions.ts | 8 ++++++++ packages/taler-wallet-core/src/wallet.ts | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json index 90ef6a453..25e7c2eb2 100644 --- a/packages/taler-wallet-core/package.json +++ b/packages/taler-wallet-core/package.json @@ -12,7 +12,7 @@ "author": "Florian Dold", "license": "GPL-3.0", "scripts": { - "compile": "jq '{version}' package.json > src/version.json && tsc --build", + "compile": "tsc --build", "pretty": "prettier --write src", "test": "tsc && ava", "coverage": "tsc && c8 --src src --all ava", diff --git a/packages/taler-wallet-core/src/versions.ts b/packages/taler-wallet-core/src/versions.ts index eedaf68f6..f0f747e22 100644 --- a/packages/taler-wallet-core/src/versions.ts +++ b/packages/taler-wallet-core/src/versions.ts @@ -34,3 +34,11 @@ export const WALLET_MERCHANT_PROTOCOL_VERSION = "2:0:1"; * Uses libtool's current:revision:age versioning. */ export const WALLET_BANK_INTEGRATION_PROTOCOL_VERSION = "0:0:0"; + +/** + * Semver of the wallet-core implementation. + * Will be replaced with the value from package.json in a + * post-compilation step (inside lib/). + */ +export const WALLET_CORE_IMPLEMENTATION_VERSION = + "__WALLET_CORE_IMPLEMENTATION_VERSION__"; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 4a83db856..aab414e94 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -300,6 +300,7 @@ import { import { TimerAPI, TimerGroup } from "./util/timer.js"; import { WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, + WALLET_CORE_IMPLEMENTATION_VERSION, WALLET_EXCHANGE_PROTOCOL_VERSION, WALLET_MERCHANT_PROTOCOL_VERSION, } from "./versions.js"; @@ -310,7 +311,6 @@ import { WalletCoreApiClient, WalletCoreResponseType, } from "./wallet-api-types.js"; -import versionInfo from "./version.json"; const logger = new Logger("wallet.ts"); @@ -1587,7 +1587,7 @@ async function dispatchRequestInternal( export function getVersion(ws: InternalWalletState): WalletCoreVersion { const result: WalletCoreVersion = { hash: undefined, - version: versionInfo.version, + version: WALLET_CORE_IMPLEMENTATION_VERSION, exchange: WALLET_EXCHANGE_PROTOCOL_VERSION, merchant: WALLET_MERCHANT_PROTOCOL_VERSION, bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, From 57e86b759e0376238f993fea1617609977fefb46 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 3 Aug 2023 19:03:24 +0200 Subject: [PATCH 11/12] rename tip->reward in URI --- packages/taler-util/src/taleruri.test.ts | 8 +++--- packages/taler-util/src/taleruri.ts | 28 +++++++++---------- packages/taler-wallet-cli/src/index.ts | 2 +- .../src/operations/reward.ts | 4 +-- .../src/NavigationBar.tsx | 2 +- .../src/platform/chrome.ts | 2 +- .../src/popup/TalerActionFound.tsx | 2 +- .../src/wallet/AddNewActionView.tsx | 2 +- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/taler-util/src/taleruri.test.ts b/packages/taler-util/src/taleruri.test.ts index 3244bbbd9..0dcf92252 100644 --- a/packages/taler-util/src/taleruri.test.ts +++ b/packages/taler-util/src/taleruri.test.ts @@ -21,7 +21,7 @@ import { parsePayUri, parseRefundUri, parseRestoreUri, - parseTipUri, + parseRewardUri, parseWithdrawExchangeUri, parseWithdrawUri, stringifyPayPushUri, @@ -161,7 +161,7 @@ test("taler refund uri parsing with instance", (t) => { test("taler tip pickup uri", (t) => { const url1 = "taler://tip/merchant.example.com/tipid"; - const r1 = parseTipUri(url1); + const r1 = parseRewardUri(url1); if (!r1) { t.fail(); return; @@ -171,7 +171,7 @@ test("taler tip pickup uri", (t) => { test("taler tip pickup uri with instance", (t) => { const url1 = "taler://tip/merchant.example.com/instances/tipm/tipid"; - const r1 = parseTipUri(url1); + const r1 = parseRewardUri(url1); if (!r1) { t.fail(); return; @@ -182,7 +182,7 @@ test("taler tip pickup uri with instance", (t) => { test("taler tip pickup uri with instance and prefix", (t) => { const url1 = "taler://tip/merchant.example.com/my/pfx/tipm/tipid"; - const r1 = parseTipUri(url1); + const r1 = parseRewardUri(url1); if (!r1) { t.fail(); return; diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts index fc140811b..777cb5245 100644 --- a/packages/taler-util/src/taleruri.ts +++ b/packages/taler-util/src/taleruri.ts @@ -26,7 +26,7 @@ export type TalerUri = | PayPushUriResult | BackupRestoreUri | RefundUriResult - | TipUriResult + | RewardUriResult | WithdrawUriResult | ExchangeUri | WithdrawExchangeUri @@ -60,8 +60,8 @@ export interface RefundUriResult { orderId: string; } -export interface TipUriResult { - type: TalerUriAction.Tip; +export interface RewardUriResult { + type: TalerUriAction.Reward; merchantBaseUrl: string; merchantTipId: string; } @@ -167,7 +167,7 @@ export enum TalerUriAction { Pay = "pay", Withdraw = "withdraw", Refund = "refund", - Tip = "tip", + Reward = "reward", PayPull = "pay-pull", PayPush = "pay-push", PayTemplate = "pay-template", @@ -212,7 +212,7 @@ const parsers: { [A in TalerUriAction]: Parser } = { [TalerUriAction.PayTemplate]: parsePayTemplateUri, [TalerUriAction.Restore]: parseRestoreUri, [TalerUriAction.Refund]: parseRefundUri, - [TalerUriAction.Tip]: parseTipUri, + [TalerUriAction.Reward]: parseRewardUri, [TalerUriAction.Withdraw]: parseWithdrawUri, [TalerUriAction.DevExperiment]: parseDevExperimentUri, [TalerUriAction.Exchange]: parseExchangeUri, @@ -255,8 +255,8 @@ export function stringifyTalerUri(uri: TalerUri): string { case TalerUriAction.Refund: { return stringifyRefundUri(uri); } - case TalerUriAction.Tip: { - return stringifyTipUri(uri); + case TalerUriAction.Reward: { + return stringifyRewardUri(uri); } case TalerUriAction.Withdraw: { return stringifyWithdrawUri(uri); @@ -394,11 +394,11 @@ export function parsePayPullUri(s: string): PayPullUriResult | undefined { } /** - * Parse a taler[+http]://tip URI. + * Parse a taler[+http]://reward URI. * Return undefined if not passed a valid URI. */ -export function parseTipUri(s: string): TipUriResult | undefined { - const pi = parseProtoInfo(s, "tip"); +export function parseRewardUri(s: string): RewardUriResult | undefined { + const pi = parseProtoInfo(s, "reward"); if (!pi) { return undefined; } @@ -416,7 +416,7 @@ export function parseTipUri(s: string): TipUriResult | undefined { ); return { - type: TalerUriAction.Tip, + type: TalerUriAction.Reward, merchantBaseUrl, merchantTipId: tipId, }; @@ -699,12 +699,12 @@ export function stringifyRefundUri({ const { proto, path } = getUrlInfo(merchantBaseUrl); return `${proto}://refund/${path}${orderId}`; } -export function stringifyTipUri({ +export function stringifyRewardUri({ merchantBaseUrl, merchantTipId, -}: Omit): string { +}: Omit): string { const { proto, path } = getUrlInfo(merchantBaseUrl); - return `${proto}://tip/${path}${merchantTipId}`; + return `${proto}://reward/${path}${merchantTipId}`; } export function stringifyExchangeUri({ diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index a34f6be03..e2787db66 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -651,7 +651,7 @@ walletCli alwaysYes: args.handleUri.autoYes, }); break; - case TalerUriAction.Tip: { + case TalerUriAction.Reward: { const res = await wallet.client.call(WalletApiOperation.PrepareReward, { talerRewardUri: uri, }); diff --git a/packages/taler-wallet-core/src/operations/reward.ts b/packages/taler-wallet-core/src/operations/reward.ts index 58c745780..47956f15f 100644 --- a/packages/taler-wallet-core/src/operations/reward.ts +++ b/packages/taler-wallet-core/src/operations/reward.ts @@ -31,7 +31,7 @@ import { j2s, Logger, NotificationType, - parseTipUri, + parseRewardUri, PrepareTipResult, TalerErrorCode, TalerPreciseTimestamp, @@ -141,7 +141,7 @@ export async function prepareTip( ws: InternalWalletState, talerTipUri: string, ): Promise { - const res = parseTipUri(talerTipUri); + const res = parseRewardUri(talerTipUri); if (!res) { throw Error("invalid taler://tip URI"); } diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 231418861..167f1797c 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -146,7 +146,7 @@ const talerUriActionToPageName: { } = { [TalerUriAction.Withdraw]: "ctaWithdraw", [TalerUriAction.Pay]: "ctaPay", - [TalerUriAction.Tip]: "ctaTips", + [TalerUriAction.Reward]: "ctaTips", [TalerUriAction.Refund]: "ctaRefund", [TalerUriAction.PayPull]: "ctaInvoicePay", [TalerUriAction.PayPush]: "ctaTransferPickup", diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index 1295fa514..a50f225dc 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -279,7 +279,7 @@ function openWalletURIFromPopup(uri: TalerUri): void { `static/wallet.html#/cta/pay?talerUri=${encodeURIComponent(talerUri)}`, ); break; - case TalerUriAction.Tip: + case TalerUriAction.Reward: url = chrome.runtime.getURL( `static/wallet.html#/cta/tip?talerUri=${encodeURIComponent(talerUri)}`, ); diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx index 6a0585907..e120334e8 100644 --- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx +++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx @@ -65,7 +65,7 @@ function ContentByUriType({
); - case TalerUriAction.Tip: + case TalerUriAction.Reward: return (

diff --git a/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx b/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx index fd9815401..fc3a0916c 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx +++ b/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx @@ -66,7 +66,7 @@ export function AddNewActionView({ onCancel }: Props): VNode { return Open pay page; case TalerUriAction.Refund: return Open refund page; - case TalerUriAction.Tip: + case TalerUriAction.Reward: return Open tip page; case TalerUriAction.Withdraw: return Open withdraw page; From ee47aa4837fedcaa8257b57138ea34fda220d2b7 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 3 Aug 2023 19:24:04 +0200 Subject: [PATCH 12/12] fix integration tests Instead of using the deprecated runUntilDone, we now wait for specific notifications. The old way doesn't work, since p2p push transactions are not considered done until the counterparty has accepted the payment. --- .../test-age-restrictions-peer.ts | 66 +++++++++++++------ .../test-peer-to-peer-pull.ts | 14 +++- .../src/operations/pay-peer-pull-credit.ts | 11 +++- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts index eae04cd2e..d15858322 100644 --- a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts +++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts @@ -17,13 +17,20 @@ /** * Imports. */ -import { AbsoluteTime, Duration } from "@gnu-taler/taler-util"; +import { + AbsoluteTime, + Duration, + NotificationType, + TransactionMajorState, + TransactionMinorState, +} from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; import { GlobalTestState, WalletCli } from "../harness/harness.js"; import { - createSimpleTestkudosEnvironment, - withdrawViaBank, + createSimpleTestkudosEnvironmentV2, + createWalletDaemonWithClient, + withdrawViaBankV2, } from "../harness/helpers.js"; /** @@ -32,12 +39,7 @@ import { export async function runAgeRestrictionsPeerTest(t: GlobalTestState) { // Set up test environment - const { - wallet: walletOne, - bank, - exchange, - merchant, - } = await createSimpleTestkudosEnvironment( + const { bank, exchange } = await createSimpleTestkudosEnvironmentV2( t, defaultCoinConfig.map((x) => x("TESTKUDOS")), { @@ -45,20 +47,29 @@ export async function runAgeRestrictionsPeerTest(t: GlobalTestState) { }, ); - const walletTwo = new WalletCli(t, "walletTwo"); - const walletThree = new WalletCli(t, "walletThree"); + const w1 = await createWalletDaemonWithClient(t, { + name: "w1", + persistent: true, + }); + const w2 = await createWalletDaemonWithClient(t, { + name: "w2", + persistent: true, + }); + + const wallet1 = w1.walletClient; + const wallet2 = w2.walletClient; { - const wallet = walletOne; - - await withdrawViaBank(t, { - wallet, + const withdrawalRes = await withdrawViaBankV2(t, { + walletClient: wallet1, bank, exchange, amount: "TESTKUDOS:20", restrictAge: 13, }); + await withdrawalRes.withdrawalFinishedCond; + const purse_expiration = AbsoluteTime.toProtocolTimestamp( AbsoluteTime.addDuration( AbsoluteTime.now(), @@ -66,7 +77,7 @@ export async function runAgeRestrictionsPeerTest(t: GlobalTestState) { ), ); - const initResp = await wallet.client.call( + const initResp = await wallet1.client.call( WalletApiOperation.InitiatePeerPushDebit, { partialContractTerms: { @@ -77,20 +88,35 @@ export async function runAgeRestrictionsPeerTest(t: GlobalTestState) { }, ); - await wallet.runUntilDone(); + const peerPushReadyCond = wallet1.waitForNotificationCond( + (x) => + x.type === NotificationType.TransactionStateTransition && + x.newTxState.major === TransactionMajorState.Pending && + x.newTxState.minor === TransactionMinorState.Ready && + x.transactionId === initResp.transactionId, + ); - const checkResp = await walletTwo.client.call( + await peerPushReadyCond; + + const checkResp = await wallet2.call( WalletApiOperation.PreparePeerPushCredit, { talerUri: initResp.talerUri, }, ); - await walletTwo.client.call(WalletApiOperation.ConfirmPeerPushCredit, { + await wallet2.call(WalletApiOperation.ConfirmPeerPushCredit, { peerPushPaymentIncomingId: checkResp.peerPushPaymentIncomingId, }); - await walletTwo.runUntilDone(); + const peerPullCreditDoneCond = wallet2.waitForNotificationCond( + (x) => + x.type === NotificationType.TransactionStateTransition && + x.newTxState.major === TransactionMajorState.Done && + x.transactionId === checkResp.transactionId, + ); + + await peerPullCreditDoneCond; } } diff --git a/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts b/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts index 30287b51b..5b55b1de1 100644 --- a/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts +++ b/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts @@ -23,6 +23,7 @@ import { j2s, NotificationType, TransactionMajorState, + TransactionMinorState, WalletNotification, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -46,12 +47,14 @@ export async function runPeerToPeerPullTest(t: GlobalTestState) { const w1 = await createWalletDaemonWithClient(t, { name: "w1", + persistent: true, handleNotification(wn) { allW1Notifications.push(wn); }, }); const w2 = await createWalletDaemonWithClient(t, { name: "w2", + persistent: true, handleNotification(wn) { allW2Notifications.push(wn); }, @@ -89,6 +92,15 @@ export async function runPeerToPeerPullTest(t: GlobalTestState) { }, ); + const peerPullCreditReadyCond = wallet1.waitForNotificationCond( + (x) => x.type === NotificationType.TransactionStateTransition && + x.transactionId === resp.transactionId && + x.newTxState.major === TransactionMajorState.Pending && + x.newTxState.minor === TransactionMinorState.Ready, + ); + + await peerPullCreditReadyCond; + const checkResp = await wallet2.client.call( WalletApiOperation.PreparePeerPullDebit, { @@ -98,8 +110,6 @@ export async function runPeerToPeerPullTest(t: GlobalTestState) { console.log(`checkResp: ${j2s(checkResp)}`); - // FIXME: The wallet should emit a more appropriate notification here. - // Yes, it's technically a withdrawal. const peerPullCreditDoneCond = wallet1.waitForNotificationCond( (x) => x.type === NotificationType.TransactionStateTransition && x.transactionId === resp.transactionId && diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts index c7e13754f..ac501aae2 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts @@ -436,16 +436,25 @@ async function handlePeerPullCreditCreatePurse( logger.info(`reserve merge response: ${j2s(resp)}`); - await ws.db + const transactionId = constructTransactionIdentifier({ + tag: TransactionType.PeerPullCredit, + pursePub: pullIni.pursePub, + }); + + const transitionInfo = await ws.db .mktx((x) => [x.peerPullPaymentInitiations]) .runReadWrite(async (tx) => { const pi2 = await tx.peerPullPaymentInitiations.get(pursePub); if (!pi2) { return; } + const oldTxState = computePeerPullCreditTransactionState(pi2); pi2.status = PeerPullPaymentInitiationStatus.PendingReady; await tx.peerPullPaymentInitiations.put(pi2); + const newTxState = computePeerPullCreditTransactionState(pi2); + return { oldTxState, newTxState }; }); + notifyTransition(ws, transactionId, transitionInfo); return TaskRunResult.finished(); }