summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-01-22 13:49:11 +0100
committerFlorian Dold <florian@dold.me>2024-01-22 13:49:11 +0100
commit88851f45403c1995c973bcae7ad2976db3c430c7 (patch)
tree8a7bbd228b7b647a4ddc22bff732b71e0c6be276 /packages/taler-wallet-core
parentd32731fc7526df18361aae6aa5541e10cf6b41aa (diff)
downloadwallet-core-88851f45403c1995c973bcae7ad2976db3c430c7.tar.gz
wallet-core-88851f45403c1995c973bcae7ad2976db3c430c7.tar.bz2
wallet-core-88851f45403c1995c973bcae7ad2976db3c430c7.zip
wallet-core: implement DD45 global currency management requests
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/db.ts69
-rw-r--r--packages/taler-wallet-core/src/util/query.ts3
-rw-r--r--packages/taler-wallet-core/src/wallet-api-types.ts67
-rw-r--r--packages/taler-wallet-core/src/wallet.ts118
4 files changed, 213 insertions, 44 deletions
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index f16600f5d..ceca24c82 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -74,6 +74,7 @@ import {
describeContents,
describeIndex,
describeStore,
+ describeStoreV2,
openDatabase,
} from "./util/query.js";
@@ -149,7 +150,7 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
* backwards-compatible way or object stores and indices
* are added.
*/
-export const WALLET_DB_MINOR_VERSION = 2;
+export const WALLET_DB_MINOR_VERSION = 3;
declare const symDbProtocolTimestamp: unique symbol;
@@ -2197,21 +2198,6 @@ export interface DbAuditorHandle {
auditorPub: string;
}
-// Work in progress for regional currencies
-export interface CurrencySettingsRecord {
- currency: string;
-
- globalScopeExchanges: DbExchangeHandle[];
-
- globalScopeAuditors: DbAuditorHandle[];
-
- // Used to decide which auditor to show the currency under
- // when multiple auditors apply.
- auditorPriority: string[];
-
- // Later, we might add stuff related to how the currency is rendered.
-}
-
export enum RefundGroupStatus {
Pending = 0x0100_0000,
Done = 0x0500_0000,
@@ -2299,18 +2285,55 @@ export function passthroughCodec<T>(): Codec<T> {
return codecForAny();
}
+export interface GlobalCurrencyAuditorRecord {
+ id?: number;
+ currency: string;
+ auditorBaseUrl: string;
+ auditorPub: string;
+}
+
+export interface GlobalCurrencyExchangeRecord {
+ id?: number;
+ currency: string;
+ exchangeBaseUrl: string;
+ exchangeMasterPub: string;
+}
+
/**
* Schema definition for the IndexedDB
* wallet database.
*/
export const WalletStoresV1 = {
- currencySettings: describeStore(
- "currencySettings",
- describeContents<CurrencySettingsRecord>({
- keyPath: ["currency"],
- }),
- {},
- ),
+ globalCurrencyAuditors: describeStoreV2({
+ recordCodec: passthroughCodec<GlobalCurrencyAuditorRecord>(),
+ storeName: "globalCurrencyAuditors",
+ keyPath: "id",
+ autoIncrement: true,
+ versionAdded: 3,
+ indexes: {
+ byCurrencyAndUrlAndPub: describeIndex("byCurrencyAndUrlAndPub", [
+ "currency",
+ "auditorBaseUrl",
+ "auditorPub",
+ ]),
+ },
+ }),
+ globalCurrencyExchanges: describeStoreV2({
+ recordCodec: passthroughCodec<GlobalCurrencyExchangeRecord>(),
+ storeName: "globalCurrencyExchanges",
+ keyPath: "id",
+ autoIncrement: true,
+ versionAdded: 3,
+ indexes: {
+ byCurrencyAndUrlAndPub: describeIndex(
+ "byCurrencyAndUrlAndPub",
+ ["currency", "exchangeBaseUrl", "exchangeMasterPub"],
+ {
+ unique: true,
+ },
+ ),
+ },
+ }),
coinAvailability: describeStore(
"coinAvailability",
describeContents<CoinAvailabilityRecord>({
diff --git a/packages/taler-wallet-core/src/util/query.ts b/packages/taler-wallet-core/src/util/query.ts
index 59c6ea2f5..efb1a3f42 100644
--- a/packages/taler-wallet-core/src/util/query.ts
+++ b/packages/taler-wallet-core/src/util/query.ts
@@ -822,7 +822,8 @@ export class DbAccess<StoreMap> {
const sn = this.db.objectStoreNames[i];
const swi = (this.stores as any)[sn] as StoreWithIndexes<any, any, any>;
if (!swi) {
- throw Error(`store metadata not available (${sn})`);
+ logger.warn(`store metadata not available (${sn})`);
+ continue;
}
storeNames.push(sn);
accessibleStores[sn] = swi;
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts
index 2cbf693f5..c02862757 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -133,6 +133,12 @@ import {
GetExchangeResourcesRequest,
DeleteExchangeRequest,
GetExchangeResourcesResponse,
+ ListGlobalCurrencyExchangesResponse,
+ ListGlobalCurrencyAuditorsResponse,
+ AddGlobalCurrencyExchangeRequest,
+ AddGlobalCurrencyAuditorRequest,
+ RemoveGlobalCurrencyExchangeRequest,
+ RemoveGlobalCurrencyAuditorRequest,
} from "@gnu-taler/taler-util";
import {
AddBackupProviderRequest,
@@ -209,7 +215,6 @@ export enum WalletApiOperation {
GetBackupInfo = "getBackupInfo",
PrepareDeposit = "prepareDeposit",
GetVersion = "getVersion",
- ListCurrencies = "listCurrencies",
GenerateDepositGroupTxId = "generateDepositGroupTxId",
CreateDepositGroup = "createDepositGroup",
SetWalletDeviceId = "setWalletDeviceId",
@@ -243,6 +248,12 @@ export enum WalletApiOperation {
TestingInfiniteTransactionLoop = "testingInfiniteTransactionLoop",
GetExchangeResources = "getExchangeResources",
DeleteExchange = "deleteExchange",
+ ListGlobalCurrencyExchanges = "listExchangeCurrencyScope",
+ ListGlobalCurrencyAuditors = "listGlobalCurrencyAuditors",
+ AddGlobalCurrencyExchange = "addGlobalCurrencyExchange",
+ RemoveGlobalCurrencyExchange = "removeGlobalCurrencyExchange",
+ AddGlobalCurrencyAuditor = "addGlobalCurrencyAuditor",
+ RemoveGlobalCurrencyAuditor = "removeGlobalCurrencyAuditor",
}
// group: Initialization
@@ -550,6 +561,44 @@ export type StartRefundQueryOp = {
response: EmptyObject;
};
+// group: Global Currency management
+
+export type ListGlobalCurrencyAuditorsOp = {
+ op: WalletApiOperation.ListGlobalCurrencyAuditors;
+ request: EmptyObject;
+ response: ListGlobalCurrencyAuditorsResponse;
+};
+
+export type ListGlobalCurrencyExchangesOp = {
+ op: WalletApiOperation.ListGlobalCurrencyExchanges;
+ request: EmptyObject;
+ response: ListGlobalCurrencyExchangesResponse;
+};
+
+export type AddGlobalCurrencyExchangeOp = {
+ op: WalletApiOperation.AddGlobalCurrencyExchange;
+ request: AddGlobalCurrencyExchangeRequest;
+ response: EmptyObject;
+};
+
+export type AddGlobalCurrencyAuditorOp = {
+ op: WalletApiOperation.AddGlobalCurrencyAuditor;
+ request: AddGlobalCurrencyAuditorRequest;
+ response: EmptyObject;
+};
+
+export type RemoveGlobalCurrencyExchangeOp = {
+ op: WalletApiOperation.RemoveGlobalCurrencyExchange;
+ request: RemoveGlobalCurrencyExchangeRequest;
+ response: EmptyObject;
+};
+
+export type RemoveGlobalCurrencyAuditorOp = {
+ op: WalletApiOperation.RemoveGlobalCurrencyAuditor;
+ request: RemoveGlobalCurrencyAuditorRequest;
+ response: EmptyObject;
+};
+
// group: Rewards
/**
@@ -690,15 +739,6 @@ export type DeleteExchangeOp = {
response: EmptyObject;
};
-/**
- * List currencies known to the wallet.
- */
-export type ListCurrenciesOp = {
- op: WalletApiOperation.ListCurrencies;
- request: EmptyObject;
- response: WalletCurrencyInfo;
-};
-
export type GetCurrencySpecificationOp = {
op: WalletApiOperation.GetCurrencySpecification;
request: GetCurrencySpecificationRequest;
@@ -1171,7 +1211,6 @@ export type WalletOperations = {
[WalletApiOperation.AcceptReward]: AcceptTipOp;
[WalletApiOperation.StartRefundQueryForUri]: StartRefundQueryForUriOp;
[WalletApiOperation.StartRefundQuery]: StartRefundQueryOp;
- [WalletApiOperation.ListCurrencies]: ListCurrenciesOp;
[WalletApiOperation.GetWithdrawalDetailsForAmount]: GetWithdrawalDetailsForAmountOp;
[WalletApiOperation.GetWithdrawalDetailsForUri]: GetWithdrawalDetailsForUriOp;
[WalletApiOperation.AcceptBankIntegratedWithdrawal]: AcceptBankIntegratedWithdrawalOp;
@@ -1231,6 +1270,12 @@ export type WalletOperations = {
[WalletApiOperation.TestingInfiniteTransactionLoop]: any;
[WalletApiOperation.DeleteExchange]: DeleteExchangeOp;
[WalletApiOperation.GetExchangeResources]: GetExchangeResourcesOp;
+ [WalletApiOperation.ListGlobalCurrencyAuditors]: ListGlobalCurrencyAuditorsOp;
+ [WalletApiOperation.ListGlobalCurrencyExchanges]: ListGlobalCurrencyExchangesOp;
+ [WalletApiOperation.AddGlobalCurrencyAuditor]: AddGlobalCurrencyAuditorOp;
+ [WalletApiOperation.RemoveGlobalCurrencyAuditor]: RemoveGlobalCurrencyAuditorOp;
+ [WalletApiOperation.AddGlobalCurrencyExchange]: AddGlobalCurrencyExchangeOp;
+ [WalletApiOperation.RemoveGlobalCurrencyExchange]: RemoveGlobalCurrencyExchangeOp;
};
export type WalletCoreRequestType<
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 3294e2a09..87c5aa995 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -39,6 +39,8 @@ import {
InitResponse,
KnownBankAccounts,
KnownBankAccountsInfo,
+ ListGlobalCurrencyAuditorsResponse,
+ ListGlobalCurrencyExchangesResponse,
Logger,
NotificationType,
PrepareWithdrawExchangeRequest,
@@ -64,6 +66,8 @@ import {
codecForAcceptPeerPullPaymentRequest,
codecForAcceptTipRequest,
codecForAddExchangeRequest,
+ codecForAddGlobalCurrencyAuditorRequest,
+ codecForAddGlobalCurrencyExchangeRequest,
codecForAddKnownBankAccounts,
codecForAny,
codecForApplyDevExperiment,
@@ -104,6 +108,8 @@ import {
codecForPrepareRewardRequest,
codecForPrepareWithdrawExchangeRequest,
codecForRecoverStoredBackupRequest,
+ codecForRemoveGlobalCurrencyAuditorRequest,
+ codecForRemoveGlobalCurrencyExchangeRequest,
codecForResumeTransaction,
codecForRetryTransactionRequest,
codecForSetCoinSuspendedRequest,
@@ -200,7 +206,6 @@ import {
lookupExchangeByUri,
updateExchangeFromUrlHandler,
} from "./operations/exchanges.js";
-import { getMerchantInfo } from "./operations/merchants.js";
import {
computePayMerchantTransactionState,
computeRefundTransactionState,
@@ -302,7 +307,7 @@ import {
GetReadOnlyAccess,
GetReadWriteAccess,
} from "./util/query.js";
-import { TimerAPI, TimerGroup, timer } from "./util/timer.js";
+import { TimerAPI, TimerGroup } from "./util/timer.js";
import {
WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION,
WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
@@ -1328,13 +1333,6 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
await setWalletDeviceId(ws, req.walletDeviceId);
return {};
}
- case WalletApiOperation.ListCurrencies: {
- // FIXME: Remove / change to scoped currency approach.
- return {
- trustedAuditors: [],
- trustedExchanges: [],
- };
- }
case WalletApiOperation.TestCrypto: {
return await ws.cryptoApi.hashString({ str: "hello world" });
}
@@ -1349,6 +1347,108 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
const dbDump = await exportDb(ws.idb);
return dbDump;
}
+ case WalletApiOperation.ListGlobalCurrencyExchanges: {
+ const resp: ListGlobalCurrencyExchangesResponse = {
+ exchanges: [],
+ };
+ await ws.db.runReadOnlyTx(["globalCurrencyExchanges"], async (tx) => {
+ const gceList = await tx.globalCurrencyExchanges.iter().toArray();
+ for (const gce of gceList) {
+ resp.exchanges.push({
+ currency: gce.currency,
+ exchangeBaseUrl: gce.exchangeBaseUrl,
+ exchangeMasterPub: gce.exchangeMasterPub,
+ });
+ }
+ });
+ return resp;
+ }
+ case WalletApiOperation.ListGlobalCurrencyAuditors: {
+ const resp: ListGlobalCurrencyAuditorsResponse = {
+ auditors: [],
+ };
+ await ws.db.runReadOnlyTx(["globalCurrencyAuditors"], async (tx) => {
+ const gcaList = await tx.globalCurrencyAuditors.iter().toArray();
+ for (const gca of gcaList) {
+ resp.auditors.push({
+ currency: gca.currency,
+ auditorBaseUrl: gca.auditorBaseUrl,
+ auditorPub: gca.auditorPub,
+ });
+ }
+ });
+ return resp;
+ }
+ case WalletApiOperation.AddGlobalCurrencyExchange: {
+ const req = codecForAddGlobalCurrencyExchangeRequest().decode(payload);
+ await ws.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
+ const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub];
+ const existingRec =
+ await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(
+ key,
+ );
+ if (existingRec) {
+ return;
+ }
+ await tx.globalCurrencyExchanges.add({
+ currency: req.currency,
+ exchangeBaseUrl: req.exchangeBaseUrl,
+ exchangeMasterPub: req.exchangeMasterPub,
+ });
+ });
+ return {};
+ }
+ case WalletApiOperation.RemoveGlobalCurrencyExchange: {
+ const req = codecForRemoveGlobalCurrencyExchangeRequest().decode(payload);
+ await ws.db.runReadWriteTx(["globalCurrencyExchanges"], async (tx) => {
+ const key = [req.currency, req.exchangeBaseUrl, req.exchangeMasterPub];
+ const existingRec =
+ await tx.globalCurrencyExchanges.indexes.byCurrencyAndUrlAndPub.get(
+ key,
+ );
+ if (!existingRec) {
+ return;
+ }
+ checkDbInvariant(!!existingRec.id);
+ await tx.globalCurrencyExchanges.delete(existingRec.id);
+ });
+ return {};
+ }
+ case WalletApiOperation.AddGlobalCurrencyAuditor: {
+ const req = codecForAddGlobalCurrencyAuditorRequest().decode(payload);
+ await ws.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
+ const key = [req.currency, req.auditorBaseUrl, req.auditorPub];
+ const existingRec =
+ await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(
+ key,
+ );
+ if (existingRec) {
+ return;
+ }
+ await tx.globalCurrencyAuditors.add({
+ currency: req.currency,
+ auditorBaseUrl: req.auditorBaseUrl,
+ auditorPub: req.auditorPub,
+ });
+ });
+ return {};
+ }
+ case WalletApiOperation.RemoveGlobalCurrencyAuditor: {
+ const req = codecForRemoveGlobalCurrencyAuditorRequest().decode(payload);
+ await ws.db.runReadWriteTx(["globalCurrencyAuditors"], async (tx) => {
+ const key = [req.currency, req.auditorBaseUrl, req.auditorPub];
+ const existingRec =
+ await tx.globalCurrencyAuditors.indexes.byCurrencyAndUrlAndPub.get(
+ key,
+ );
+ if (!existingRec) {
+ return;
+ }
+ checkDbInvariant(!!existingRec.id);
+ await tx.globalCurrencyAuditors.delete(existingRec.id);
+ });
+ return {};
+ }
case WalletApiOperation.ImportDb: {
const req = codecForImportDbRequest().decode(payload);
await importDb(ws.db.idbHandle(), req.dump);