aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/wallet.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/wallet.ts')
-rw-r--r--packages/taler-wallet-core/src/wallet.ts1243
1 files changed, 696 insertions, 547 deletions
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index 1f2686cc9..9c870531e 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -57,6 +57,8 @@ import {
FailTransactionRequest,
ForgetKnownBankAccountsRequest,
GetActiveTasksResponse,
+ GetBankingChoicesForPaytoRequest,
+ GetBankingChoicesForPaytoResponse,
GetContractTermsDetailsRequest,
GetCurrencySpecificationRequest,
GetCurrencySpecificationResponse,
@@ -76,6 +78,7 @@ import {
ListExchangesForScopedCurrencyRequest,
ListGlobalCurrencyAuditorsResponse,
ListGlobalCurrencyExchangesResponse,
+ ListKnownBankAccountsRequest,
Logger,
NotificationType,
ObservabilityContext,
@@ -102,9 +105,9 @@ import {
TestingGetDenomStatsResponse,
TestingGetReserveHistoryRequest,
TestingSetTimetravelRequest,
- TestingWaitTransactionRequest,
TimerAPI,
TimerGroup,
+ TransactionIdStr,
TransactionType,
TransactionsResponse,
UpdateExchangeEntryRequest,
@@ -114,6 +117,7 @@ import {
WalletCoreVersion,
WalletNotification,
WalletRunConfig,
+ WireTypeDetails,
WithdrawTestBalanceRequest,
canonicalizeBaseUrl,
checkDbInvariant,
@@ -129,6 +133,7 @@ import {
codecForAny,
codecForApplyDevExperiment,
codecForCanonicalizeBaseUrlRequest,
+ codecForCheckDepositRequest,
codecForCheckPayTemplateRequest,
codecForCheckPeerPullPaymentRequest,
codecForCheckPeerPushDebitRequest,
@@ -144,15 +149,18 @@ import {
codecForFailTransactionRequest,
codecForForceRefreshRequest,
codecForForgetKnownBankAccounts,
- codecForGetAmountRequest,
codecForGetBalanceDetailRequest,
+ codecForGetBankingChoicesForPaytoRequest,
codecForGetContractTermsDetails,
codecForGetCurrencyInfoRequest,
codecForGetDepositWireTypesForCurrencyRequest,
codecForGetExchangeEntryByUrlRequest,
codecForGetExchangeResourcesRequest,
codecForGetExchangeTosRequest,
+ codecForGetMaxDepositAmountRequest,
+ codecForGetMaxPeerPushDebitAmountRequest,
codecForGetQrCodesForPaytoRequest,
+ codecForGetTransactionsV2Request,
codecForGetWithdrawalDetailsForAmountRequest,
codecForGetWithdrawalDetailsForUri,
codecForHintNetworkAvailabilityRequest,
@@ -165,7 +173,6 @@ import {
codecForListExchangesForScopedCurrencyRequest,
codecForListKnownBankAccounts,
codecForPrepareBankIntegratedWithdrawalRequest,
- codecForPrepareDepositRequest,
codecForPreparePayRequest,
codecForPreparePayTemplateRequest,
codecForPreparePeerPullPaymentRequest,
@@ -180,12 +187,14 @@ import {
codecForSetCoinSuspendedRequest,
codecForSetWalletDeviceIdRequest,
codecForSharePaymentRequest,
+ codecForStartExchangeWalletKycRequest,
codecForStartRefundQueryRequest,
codecForSuspendTransaction,
codecForTestPayArgs,
codecForTestingGetDenomStatsRequest,
codecForTestingGetReserveHistoryRequest,
codecForTestingSetTimetravelRequest,
+ codecForTestingWaitWalletKycRequest,
codecForTransactionByIdRequest,
codecForTransactionsRequest,
codecForUpdateExchangeEntryRequest,
@@ -214,7 +223,6 @@ import {
markAttentionRequestAsRead,
} from "./attention.js";
import {
- RunBackupCycleRequest,
addBackupProvider,
codecForAddBackupProviderRequest,
codecForRemoveBackupProvider,
@@ -227,6 +235,10 @@ import {
setWalletDeviceId,
} from "./backup/index.js";
import { getBalanceDetail, getBalances } from "./balance.js";
+import {
+ getMaxDepositAmount,
+ getMaxPeerPushDebitAmount,
+} from "./coinSelection.js";
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
import {
CryptoDispatcher,
@@ -264,16 +276,13 @@ import {
getExchangeResources,
getExchangeTos,
getExchangeWireDetailsInTx,
+ handleStartExchangeWalletKyc,
+ handleTestingWaitExchangeState,
+ handleTestingWaitExchangeWalletKyc,
listExchanges,
lookupExchangeByUri,
} from "./exchanges.js";
-import {
- convertDepositAmount,
- convertPeerPushAmount,
- convertWithdrawalAmount,
- getMaxDepositAmount,
- getMaxPeerPushAmount,
-} from "./instructedAmountConversion.js";
+import { convertDepositAmount } from "./instructedAmountConversion.js";
import {
ObservableDbAccess,
ObservableTaskScheduler,
@@ -290,7 +299,7 @@ import {
startRefundQueryForUri,
} from "./pay-merchant.js";
import {
- checkPeerPullPaymentInitiation,
+ checkPeerPullCredit,
initiatePeerPullPayment,
} from "./pay-peer-pull-credit.js";
import {
@@ -335,8 +344,9 @@ import {
failTransaction,
getTransactionById,
getTransactions,
- getWithdrawalTransactionByUri,
+ getTransactionsV2,
parseTransactionIdentifier,
+ rematerializeTransactions,
restartAll as restartAllRunningTasks,
resumeTransaction,
retryAll,
@@ -380,6 +390,7 @@ export interface WalletExecutionContext {
readonly http: HttpRequestLibrary;
readonly db: DbAccess<typeof WalletStoresV1>;
readonly oc: ObservabilityContext;
+ readonly cts: CancellationToken.Source | undefined;
readonly taskScheduler: TaskScheduler;
}
@@ -427,6 +438,41 @@ async function fillDefaults(wex: WalletExecutionContext): Promise<void> {
}
}
+/**
+ * Incremented each time we want to re-materialize transactions.
+ */
+const MATERIALIZED_TRANSACTIONS_VERSION = 1;
+
+async function migrateMaterializedTransactions(
+ wex: WalletExecutionContext,
+): Promise<void> {
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ const ver = await tx.config.get("materializedTransactionsVersion");
+ if (ver) {
+ if (ver.key !== ConfigRecordKey.MaterializedTransactionsVersion) {
+ logger.error("invalid configuration (materializedTransactionsVersion)");
+ return;
+ }
+ if (ver.value == MATERIALIZED_TRANSACTIONS_VERSION) {
+ return;
+ }
+ if (ver.value > MATERIALIZED_TRANSACTIONS_VERSION) {
+ logger.error(
+ "database is newer than code (materializedTransactionsVersion)",
+ );
+ return;
+ }
+ }
+
+ await rematerializeTransactions(wex, tx);
+
+ await tx.config.put({
+ key: ConfigRecordKey.MaterializedTransactionsVersion,
+ value: MATERIALIZED_TRANSACTIONS_VERSION,
+ });
+ });
+}
+
export async function getDenomInfo(
wex: WalletExecutionContext,
tx: WalletDbReadOnlyTransaction<["denominations"]>,
@@ -451,11 +497,12 @@ export async function getDenomInfo(
* List bank accounts known to the wallet from
* previous withdrawals.
*/
-async function listKnownBankAccounts(
+async function handleListKnownBankAccounts(
wex: WalletExecutionContext,
- currency?: string,
+ req: ListKnownBankAccountsRequest,
): Promise<KnownBankAccounts> {
const accounts: KnownBankAccountsInfo[] = [];
+ const currency = req.currency;
await wex.db.runReadOnlyTx({ storeNames: ["bankAccounts"] }, async (tx) => {
const knownAccounts = await tx.bankAccounts.iter().toArray();
for (const r of knownAccounts) {
@@ -624,7 +671,12 @@ async function getClientFromWalletState(
const client: WalletCoreApiClient = {
async call(op, payload): Promise<any> {
id = (id + 1) % (Number.MAX_SAFE_INTEGER - 100);
- const res = await handleCoreApiRequest(ws, op, String(id), payload);
+ const res = await dispatchWalletCoreApiRequest(
+ ws,
+ op,
+ String(id),
+ payload,
+ );
switch (res.type) {
case "error":
throw TalerError.fromUncheckedDetail(res.error);
@@ -701,6 +753,9 @@ async function recoverStoredBackup(
});
logger.info(`backup found, now importing`);
await importDb(wex.db.idbHandle(), bd);
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await rematerializeTransactions(wex, tx);
+ });
logger.info(`import done`);
}
@@ -790,8 +845,11 @@ async function handleSetWalletRunConfig(
logger.trace("filling defaults");
await fillDefaults(wex);
}
+
+ await migrateMaterializedTransactions(wex);
+
const resp: InitResponse = {
- versionInfo: handleGetVersion(wex),
+ versionInfo: await handleGetVersion(wex),
};
if (req.config?.lazyTaskLoop) {
@@ -1008,6 +1066,50 @@ async function handleGetQrCodesForPayto(
};
}
+async function handleGetBankingChoicesForPayto(
+ wex: WalletExecutionContext,
+ req: GetBankingChoicesForPaytoRequest,
+): Promise<GetBankingChoicesForPaytoResponse> {
+ const parsedPayto = parsePaytoUri(req.paytoUri);
+ if (!parsedPayto) {
+ throw Error("invalid payto URI");
+ }
+ const amount = parsedPayto.params["amount"];
+ if (!amount) {
+ logger.warn("payto URI has no amount");
+ return {
+ choices: [],
+ };
+ }
+ const currency = Amounts.currencyOf(amount);
+ switch (currency) {
+ case "KUDOS":
+ return {
+ choices: [
+ {
+ label: "Demobank Website",
+ type: "link",
+ uri: `https://bank.demo.taler.net/webui/#/transfer/${encodeURIComponent(
+ req.paytoUri,
+ )}`,
+ },
+ {
+ label: "Demobank App",
+ type: "link",
+ uri: `https://bank.demo.taler.net/app/transfer/${encodeURIComponent(
+ req.paytoUri,
+ )}`,
+ },
+ ],
+ };
+ break;
+ default:
+ return {
+ choices: [],
+ };
+ }
+}
+
async function handleConfirmPay(
wex: WalletExecutionContext,
req: ConfirmPayRequest,
@@ -1118,18 +1220,14 @@ async function handleStartRefundQuery(
return {};
}
-async function handleAddBackupProvider(
- wex: WalletExecutionContext,
- req: RunBackupCycleRequest,
-): Promise<EmptyObject> {
- await runBackupCycle(wex, req);
- return {};
-}
-
async function handleHintNetworkAvailability(
wex: WalletExecutionContext,
req: HintNetworkAvailabilityRequest,
): Promise<EmptyObject> {
+ // If network was already available, don't do anything
+ if (wex.ws.networkAvailable === req.isNetworkAvailable) {
+ return {};
+ }
wex.ws.networkAvailable = req.isNetworkAvailable;
// When network becomes available, restart tasks as they're blocked
// waiting for the network.
@@ -1144,6 +1242,8 @@ async function handleGetDepositWireTypesForCurrency(
req: GetDepositWireTypesForCurrencyRequest,
): Promise<GetDepositWireTypesForCurrencyResponse> {
const wtSet: Set<string> = new Set();
+ const wireTypeDetails: WireTypeDetails[] = [];
+ const talerBankHostnames: string[] = [];
await wex.db.runReadOnlyTx(
{ storeNames: ["exchanges", "exchangeDetails"] },
async (tx) => {
@@ -1165,25 +1265,42 @@ async function handleGetDepositWireTypesForCurrency(
}
}
if (!usable) {
- break;
+ continue;
}
const parsedPayto = parsePaytoUri(acc.payto_uri);
if (!parsedPayto) {
continue;
}
- wtSet.add(parsedPayto.targetType);
+ if (
+ parsedPayto.isKnown &&
+ parsedPayto.targetType === "x-taler-bank"
+ ) {
+ if (!talerBankHostnames.includes(parsedPayto.host)) {
+ talerBankHostnames.push(parsedPayto.host);
+ }
+ }
+ if (!wtSet.has(parsedPayto.targetType)) {
+ wtSet.add(parsedPayto.targetType);
+ wireTypeDetails.push({
+ paymentTargetType: parsedPayto.targetType,
+ // Will possibly extended later by other exchanges
+ // with the same wire type.
+ talerBankHostnames,
+ });
+ }
}
}
},
);
return {
wireTypes: [...wtSet],
+ wireTypeDetails,
};
}
async function handleListGlobalCurrencyExchanges(
wex: WalletExecutionContext,
- req: EmptyObject,
+ _req: EmptyObject,
): Promise<ListGlobalCurrencyExchangesResponse> {
const resp: ListGlobalCurrencyExchangesResponse = {
exchanges: [],
@@ -1206,7 +1323,7 @@ async function handleListGlobalCurrencyExchanges(
async function handleListGlobalCurrencyAuditors(
wex: WalletExecutionContext,
- req: EmptyObject,
+ _req: EmptyObject,
): Promise<ListGlobalCurrencyAuditorsResponse> {
const resp: ListGlobalCurrencyAuditorsResponse = {
auditors: [],
@@ -1323,7 +1440,7 @@ async function handleAddGlobalCurrencyAuditor(
async function handleShutdown(
wex: WalletExecutionContext,
- req: EmptyObject,
+ _req: EmptyObject,
): Promise<EmptyObject> {
wex.ws.stop();
return {};
@@ -1339,7 +1456,7 @@ async function handleTestingSetTimetravel(
}
async function handleCanonicalizeBaseUrl(
- wex: WalletExecutionContext,
+ _wex: WalletExecutionContext,
req: CanonicalizeBaseUrlRequest,
): Promise<CanonicalizeBaseUrlResponse> {
return {
@@ -1357,7 +1474,7 @@ async function handleDeleteExchange(
async function handleCreateStoredBackup(
wex: WalletExecutionContext,
- req: EmptyObject,
+ _req: EmptyObject,
): Promise<CreateStoredBackupResponse> {
return await createStoredBackup(wex);
}
@@ -1375,6 +1492,93 @@ async function handleAcceptBankIntegratedWithdrawal(
});
}
+async function handleGetCurrencySpecification(
+ wex: WalletExecutionContext,
+ req: GetCurrencySpecificationRequest,
+): Promise<GetCurrencySpecificationResponse> {
+ const spec = await wex.db.runReadOnlyTx(
+ {
+ storeNames: ["currencyInfo"],
+ },
+ async (tx) => {
+ return WalletDbHelpers.getCurrencyInfo(tx, req.scope);
+ },
+ );
+ if (spec) {
+ return {
+ currencySpecification: spec.currencySpec,
+ };
+ }
+ // Hard-coded mock for KUDOS and TESTKUDOS
+ if (req.scope.currency === "KUDOS") {
+ const kudosResp: GetCurrencySpecificationResponse = {
+ currencySpecification: {
+ name: "Kudos (Taler Demonstrator)",
+ num_fractional_input_digits: 2,
+ num_fractional_normal_digits: 2,
+ num_fractional_trailing_zero_digits: 2,
+ alt_unit_names: {
+ "0": "ク",
+ },
+ },
+ };
+ return kudosResp;
+ } else if (req.scope.currency === "TESTKUDOS") {
+ const testkudosResp: GetCurrencySpecificationResponse = {
+ currencySpecification: {
+ name: "Test (Taler Unstable Demonstrator)",
+ num_fractional_input_digits: 0,
+ num_fractional_normal_digits: 0,
+ num_fractional_trailing_zero_digits: 0,
+ alt_unit_names: {
+ "0": "テ",
+ },
+ },
+ };
+ return testkudosResp;
+ }
+ const defaultResp: GetCurrencySpecificationResponse = {
+ currencySpecification: {
+ name: req.scope.currency,
+ num_fractional_input_digits: 2,
+ num_fractional_normal_digits: 2,
+ num_fractional_trailing_zero_digits: 2,
+ alt_unit_names: {
+ "0": req.scope.currency,
+ },
+ },
+ };
+ return defaultResp;
+}
+
+export async function handleHintApplicationResumed(
+ wex: WalletExecutionContext,
+ req: EmptyObject,
+): Promise<EmptyObject> {
+ logger.info("handling hintApplicationResumed");
+ await restartAllRunningTasks(wex);
+ return {};
+}
+
+async function handleGetVersion(
+ wex: WalletExecutionContext,
+): Promise<WalletCoreVersion> {
+ const result: WalletCoreVersion = {
+ implementationSemver: walletCoreBuildInfo.implementationSemver,
+ implementationGitHash: walletCoreBuildInfo.implementationGitHash,
+ hash: undefined,
+ version: WALLET_CORE_API_PROTOCOL_VERSION,
+ exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
+ merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
+ bankConversionApiRange: WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION,
+ bankIntegrationApiRange: TalerBankIntegrationHttpClient.PROTOCOL_VERSION,
+ corebankApiRange: WALLET_COREBANK_API_PROTOCOL_VERSION,
+ bank: TalerBankIntegrationHttpClient.PROTOCOL_VERSION,
+ devMode: wex.ws.config.testing.devModeActive,
+ };
+ return result;
+}
+
interface HandlerWithValidator<Tag extends WalletApiOperation> {
codec: Codec<WalletCoreRequestType<Tag>>;
handler: (
@@ -1383,8 +1587,15 @@ interface HandlerWithValidator<Tag extends WalletApiOperation> {
) => Promise<WalletCoreResponseType<Tag>>;
}
-// @ts-ignore
const handlers: { [T in WalletApiOperation]: HandlerWithValidator<T> } = {
+ [WalletApiOperation.TestingWaitExchangeState]: {
+ codec: codecForAny(),
+ handler: handleTestingWaitExchangeState,
+ },
+ [WalletApiOperation.HintApplicationResumed]: {
+ codec: codecForEmptyObject(),
+ handler: handleHintApplicationResumed,
+ },
[WalletApiOperation.AbortTransaction]: {
codec: codecForAbortTransaction(),
handler: handleAbortTransaction,
@@ -1442,14 +1653,14 @@ const handlers: { [T in WalletApiOperation]: HandlerWithValidator<T> } = {
codec: codecForTransactionsRequest(),
handler: getTransactions,
},
+ [WalletApiOperation.GetTransactionsV2]: {
+ codec: codecForGetTransactionsV2Request(),
+ handler: getTransactionsV2,
+ },
[WalletApiOperation.GetTransactionById]: {
codec: codecForTransactionByIdRequest(),
handler: getTransactionById,
},
- [WalletApiOperation.GetWithdrawalTransactionByUri]: {
- codec: codecForGetWithdrawalDetailsForUri(),
- handler: getWithdrawalTransactionByUri,
- },
[WalletApiOperation.AddExchange]: {
codec: codecForAddExchangeRequest(),
handler: handleAddExchange,
@@ -1482,564 +1693,503 @@ const handlers: { [T in WalletApiOperation]: HandlerWithValidator<T> } = {
codec: codecForAddExchangeRequest(),
handler: (wex, req) => getExchangeDetailedInfo(wex, req.exchangeBaseUrl),
},
-};
-
-/**
- * Implementation of the "wallet-core" API.
- */
-async function dispatchRequestInternal(
- wex: WalletExecutionContext,
- cts: CancellationToken.Source,
- operation: WalletApiOperation,
- payload: unknown,
-): Promise<WalletCoreResponseType<typeof operation>> {
- if (!wex.ws.initCalled && operation !== WalletApiOperation.InitWallet) {
- throw Error(
- `wallet must be initialized before running operation ${operation}`,
- );
- }
- // FIXME: Can we make this more type-safe by using the request/response type
- // definitions we already have?
- switch (operation) {
- case WalletApiOperation.CreateStoredBackup:
- return await handleCreateStoredBackup(wex, {});
- case WalletApiOperation.DeleteStoredBackup: {
- const req = codecForDeleteStoredBackupRequest().decode(payload);
- return await handleDeleteStoredBackup(wex, req);
- }
- case WalletApiOperation.ListStoredBackups:
- return listStoredBackups(wex);
- case WalletApiOperation.RecoverStoredBackup: {
- const req = codecForRecoverStoredBackupRequest().decode(payload);
- return await handleRecoverStoredBackup(wex, req);
- }
- case WalletApiOperation.SetWalletRunConfig:
- case WalletApiOperation.InitWallet: {
- const req = codecForInitRequest().decode(payload);
- return await handleSetWalletRunConfig(wex, req);
- }
- case WalletApiOperation.WithdrawTestkudos: {
- return await handleWithdrawTestkudos(wex);
- }
- case WalletApiOperation.WithdrawTestBalance: {
- const req = codecForWithdrawTestBalance().decode(payload);
- return await handleWithdrawTestBalance(wex, req);
- }
- case WalletApiOperation.RunIntegrationTest: {
- const req = codecForIntegrationTestArgs().decode(payload);
- return await handleRunIntegrationTest(wex, req);
- }
- case WalletApiOperation.RunIntegrationTestV2: {
- const req = codecForIntegrationTestV2Args().decode(payload);
- return await handleRunIntegrationTestV2(wex, req);
- }
- case WalletApiOperation.ValidateIban: {
- const req = codecForValidateIbanRequest().decode(payload);
- return handleValidateIban(wex, req);
- }
- case WalletApiOperation.TestPay: {
- const req = codecForTestPayArgs().decode(payload);
- return await testPay(wex, req);
- }
- case WalletApiOperation.GetTransactions: {
- const req = codecForTransactionsRequest().decode(payload);
- return await getTransactions(wex, req);
- }
- case WalletApiOperation.GetTransactionById: {
- const req = codecForTransactionByIdRequest().decode(payload);
- return await getTransactionById(wex, req);
- }
- case WalletApiOperation.GetWithdrawalTransactionByUri: {
- const req = codecForGetWithdrawalDetailsForUri().decode(payload);
- return await getWithdrawalTransactionByUri(wex, req);
- }
- case WalletApiOperation.AddExchange: {
- const req = codecForAddExchangeRequest().decode(payload);
- return await handleAddExchange(wex, req);
- }
- case WalletApiOperation.TestingPing: {
+ [WalletApiOperation.ListKnownBankAccounts]: {
+ codec: codecForListKnownBankAccounts(),
+ handler: handleListKnownBankAccounts,
+ },
+ [WalletApiOperation.AddKnownBankAccounts]: {
+ codec: codecForAddKnownBankAccounts(),
+ handler: handleAddKnownBankAccount,
+ },
+ [WalletApiOperation.ForgetKnownBankAccounts]: {
+ codec: codecForForgetKnownBankAccounts(),
+ handler: handleForgetKnownBankAccounts,
+ },
+ [WalletApiOperation.GetWithdrawalDetailsForUri]: {
+ codec: codecForGetWithdrawalDetailsForUri(),
+ handler: (wex, req) =>
+ getWithdrawalDetailsForUri(wex, req.talerWithdrawUri),
+ },
+ [WalletApiOperation.TestingGetReserveHistory]: {
+ codec: codecForTestingGetReserveHistoryRequest(),
+ handler: handleTestingGetReserveHistory,
+ },
+ [WalletApiOperation.AcceptManualWithdrawal]: {
+ codec: codecForAcceptManualWithdrawalRequest(),
+ handler: handleAcceptManualWithdrawal,
+ },
+ [WalletApiOperation.GetWithdrawalDetailsForAmount]: {
+ codec: codecForGetWithdrawalDetailsForAmountRequest(),
+ handler: getWithdrawalDetailsForAmount,
+ },
+ [WalletApiOperation.GetBalances]: {
+ codec: codecForEmptyObject(),
+ handler: getBalances,
+ },
+ [WalletApiOperation.GetBalanceDetail]: {
+ codec: codecForGetBalanceDetailRequest(),
+ handler: getBalanceDetail,
+ },
+ [WalletApiOperation.GetUserAttentionRequests]: {
+ codec: codecForUserAttentionsRequest(),
+ handler: getUserAttentions,
+ },
+ [WalletApiOperation.MarkAttentionRequestAsRead]: {
+ codec: codecForUserAttentionByIdRequest(),
+ handler: async (wex, req) => {
+ await markAttentionRequestAsRead(wex, req);
return {};
- }
- case WalletApiOperation.UpdateExchangeEntry: {
- const req = codecForUpdateExchangeEntryRequest().decode(payload);
- return await handleUpdateExchangeEntry(wex, req);
- }
- case WalletApiOperation.TestingGetDenomStats: {
- const req = codecForTestingGetDenomStatsRequest().decode(payload);
- return handleTestingGetDenomStats(wex, req);
- }
- case WalletApiOperation.ListExchanges: {
- return await listExchanges(wex);
- }
- case WalletApiOperation.GetExchangeEntryByUrl: {
- const req = codecForGetExchangeEntryByUrlRequest().decode(payload);
- return lookupExchangeByUri(wex, req);
- }
- case WalletApiOperation.ListExchangesForScopedCurrency: {
- const req =
- codecForListExchangesForScopedCurrencyRequest().decode(payload);
- return await handleListExchangesForScopedCurrency(wex, req);
- }
- case WalletApiOperation.GetExchangeDetailedInfo: {
- const req = codecForAddExchangeRequest().decode(payload);
- return await getExchangeDetailedInfo(wex, req.exchangeBaseUrl);
- }
- case WalletApiOperation.ListKnownBankAccounts: {
- const req = codecForListKnownBankAccounts().decode(payload);
- return await listKnownBankAccounts(wex, req.currency);
- }
- case WalletApiOperation.AddKnownBankAccounts: {
- const req = codecForAddKnownBankAccounts().decode(payload);
- return await handleAddKnownBankAccount(wex, req);
- }
- case WalletApiOperation.ForgetKnownBankAccounts: {
- const req = codecForForgetKnownBankAccounts().decode(payload);
- return await handleForgetKnownBankAccounts(wex, req);
- }
- case WalletApiOperation.GetWithdrawalDetailsForUri: {
- const req = codecForGetWithdrawalDetailsForUri().decode(payload);
- return await getWithdrawalDetailsForUri(wex, req.talerWithdrawUri);
- }
- case WalletApiOperation.TestingGetReserveHistory: {
- const req = codecForTestingGetReserveHistoryRequest().decode(payload);
- return await handleTestingGetReserveHistory(wex, req);
- }
- case WalletApiOperation.AcceptManualWithdrawal: {
- const req = codecForAcceptManualWithdrawalRequest().decode(payload);
- return await handleAcceptManualWithdrawal(wex, req);
- }
- case WalletApiOperation.GetWithdrawalDetailsForAmount: {
- const req =
- codecForGetWithdrawalDetailsForAmountRequest().decode(payload);
- return await getWithdrawalDetailsForAmount(wex, cts, req);
- }
- case WalletApiOperation.GetBalances: {
- return await getBalances(wex);
- }
- case WalletApiOperation.GetBalanceDetail: {
- const req = codecForGetBalanceDetailRequest().decode(payload);
- return await getBalanceDetail(wex, req);
- }
- case WalletApiOperation.GetUserAttentionRequests: {
- const req = codecForUserAttentionsRequest().decode(payload);
- return await getUserAttentions(wex, req);
- }
- case WalletApiOperation.MarkAttentionRequestAsRead: {
- const req = codecForUserAttentionByIdRequest().decode(payload);
- return await markAttentionRequestAsRead(wex, req);
- }
- case WalletApiOperation.GetUserAttentionUnreadCount: {
- const req = codecForUserAttentionsRequest().decode(payload);
- return await getUserAttentionsUnreadCount(wex, req);
- }
- case WalletApiOperation.SetExchangeTosAccepted: {
- const req = codecForAcceptExchangeTosRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.GetUserAttentionUnreadCount]: {
+ codec: codecForUserAttentionsRequest(),
+ handler: getUserAttentionsUnreadCount,
+ },
+ [WalletApiOperation.SetExchangeTosAccepted]: {
+ codec: codecForAcceptExchangeTosRequest(),
+ handler: async (wex, req) => {
await acceptExchangeTermsOfService(wex, req.exchangeBaseUrl);
return {};
- }
- case WalletApiOperation.SetExchangeTosForgotten: {
- const req = codecForAcceptExchangeTosRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.SetExchangeTosForgotten]: {
+ codec: codecForAcceptExchangeTosRequest(),
+ handler: async (wex, req) => {
await forgetExchangeTermsOfService(wex, req.exchangeBaseUrl);
return {};
- }
- case WalletApiOperation.AcceptBankIntegratedWithdrawal: {
- const req =
- codecForAcceptBankIntegratedWithdrawalRequest().decode(payload);
- return handleAcceptBankIntegratedWithdrawal(wex, req);
- }
- case WalletApiOperation.ConfirmWithdrawal: {
- const req = codecForConfirmWithdrawalRequestRequest().decode(payload);
- return confirmWithdrawal(wex, req);
- }
- case WalletApiOperation.PrepareBankIntegratedWithdrawal: {
- const req =
- codecForPrepareBankIntegratedWithdrawalRequest().decode(payload);
- return prepareBankIntegratedWithdrawal(wex, req);
- }
- case WalletApiOperation.GetExchangeTos: {
- const req = codecForGetExchangeTosRequest().decode(payload);
- return await handleGetExchangeTos(wex, req);
- }
- case WalletApiOperation.GetContractTermsDetails: {
- const req = codecForGetContractTermsDetails().decode(payload);
- return handleGetContractTermsDetails(wex, req);
- }
- case WalletApiOperation.RetryPendingNow: {
- return handleRetryPendingNow(wex);
- }
- case WalletApiOperation.SharePayment: {
- const req = codecForSharePaymentRequest().decode(payload);
- return await handleSharePayment(wex, req);
- }
- case WalletApiOperation.PrepareWithdrawExchange: {
- const req = codecForPrepareWithdrawExchangeRequest().decode(payload);
- return await handlePrepareWithdrawExchange(wex, req);
- }
- case WalletApiOperation.CheckPayForTemplate: {
- const req = codecForCheckPayTemplateRequest().decode(payload);
- return await checkPayForTemplate(wex, req);
- }
- case WalletApiOperation.PreparePayForUri: {
- const req = codecForPreparePayRequest().decode(payload);
- return await preparePayForUri(wex, req.talerPayUri);
- }
- case WalletApiOperation.PreparePayForTemplate: {
- const req = codecForPreparePayTemplateRequest().decode(payload);
- return preparePayForTemplate(wex, req);
- }
- case WalletApiOperation.GetQrCodesForPayto: {
- const req = codecForGetQrCodesForPaytoRequest().decode(payload);
- return handleGetQrCodesForPayto(wex, req);
- }
- case WalletApiOperation.ConfirmPay: {
- const req = codecForConfirmPayRequest().decode(payload);
- return handleConfirmPay(wex, req);
- }
- case WalletApiOperation.AbortTransaction: {
- const req = codecForAbortTransaction().decode(payload);
- return handleAbortTransaction(wex, req);
- }
- case WalletApiOperation.SuspendTransaction: {
- const req = codecForSuspendTransaction().decode(payload);
- return handleSuspendTransaction(wex, req);
- }
- case WalletApiOperation.GetActiveTasks: {
- return await handleGetActiveTasks(wex, {});
- }
- case WalletApiOperation.FailTransaction: {
- const req = codecForFailTransactionRequest().decode(payload);
- return await handleFailTransaction(wex, req);
- }
- case WalletApiOperation.ResumeTransaction: {
- const req = codecForResumeTransaction().decode(payload);
+ },
+ },
+ [WalletApiOperation.AcceptBankIntegratedWithdrawal]: {
+ codec: codecForAcceptBankIntegratedWithdrawalRequest(),
+ handler: handleAcceptBankIntegratedWithdrawal,
+ },
+ [WalletApiOperation.ConfirmWithdrawal]: {
+ codec: codecForConfirmWithdrawalRequestRequest(),
+ handler: confirmWithdrawal,
+ },
+ [WalletApiOperation.PrepareBankIntegratedWithdrawal]: {
+ codec: codecForPrepareBankIntegratedWithdrawalRequest(),
+ handler: prepareBankIntegratedWithdrawal,
+ },
+ [WalletApiOperation.GetExchangeTos]: {
+ codec: codecForGetExchangeTosRequest(),
+ handler: handleGetExchangeTos,
+ },
+ [WalletApiOperation.GetContractTermsDetails]: {
+ codec: codecForGetContractTermsDetails(),
+ handler: handleGetContractTermsDetails,
+ },
+ [WalletApiOperation.RetryPendingNow]: {
+ codec: codecForEmptyObject(),
+ handler: handleRetryPendingNow,
+ },
+ [WalletApiOperation.SharePayment]: {
+ codec: codecForSharePaymentRequest(),
+ handler: handleSharePayment,
+ },
+ [WalletApiOperation.PrepareWithdrawExchange]: {
+ codec: codecForPrepareWithdrawExchangeRequest(),
+ handler: handlePrepareWithdrawExchange,
+ },
+ [WalletApiOperation.CheckPayForTemplate]: {
+ codec: codecForCheckPayTemplateRequest(),
+ handler: checkPayForTemplate,
+ },
+ [WalletApiOperation.PreparePayForUri]: {
+ codec: codecForPreparePayRequest(),
+ handler: (wex, req) => preparePayForUri(wex, req.talerPayUri),
+ },
+ [WalletApiOperation.PreparePayForTemplate]: {
+ codec: codecForPreparePayTemplateRequest(),
+ handler: preparePayForTemplate,
+ },
+ [WalletApiOperation.GetQrCodesForPayto]: {
+ codec: codecForGetQrCodesForPaytoRequest(),
+ handler: handleGetQrCodesForPayto,
+ },
+ [WalletApiOperation.ConfirmPay]: {
+ codec: codecForConfirmPayRequest(),
+ handler: handleConfirmPay,
+ },
+ [WalletApiOperation.SuspendTransaction]: {
+ codec: codecForSuspendTransaction(),
+ handler: handleSuspendTransaction,
+ },
+ [WalletApiOperation.GetActiveTasks]: {
+ codec: codecForEmptyObject(),
+ handler: handleGetActiveTasks,
+ },
+ [WalletApiOperation.FailTransaction]: {
+ codec: codecForFailTransactionRequest(),
+ handler: handleFailTransaction,
+ },
+ [WalletApiOperation.ResumeTransaction]: {
+ codec: codecForResumeTransaction(),
+ handler: async (wex, req) => {
await resumeTransaction(wex, req.transactionId);
return {};
- }
- case WalletApiOperation.DumpCoins: {
- return await dumpCoins(wex);
- }
- case WalletApiOperation.SetCoinSuspended: {
- const req = codecForSetCoinSuspendedRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.DumpCoins]: {
+ codec: codecForEmptyObject(),
+ handler: dumpCoins,
+ },
+ [WalletApiOperation.SetCoinSuspended]: {
+ codec: codecForSetCoinSuspendedRequest(),
+ handler: async (wex, req) => {
await setCoinSuspended(wex, req.coinPub, req.suspended);
return {};
- }
- case WalletApiOperation.TestingGetSampleTransactions:
- const req = codecForEmptyObject().decode(payload);
- return handleTestingGetSampleTransactions(wex, req);
- case WalletApiOperation.ForceRefresh: {
- const req = codecForForceRefreshRequest().decode(payload);
- return await forceRefresh(wex, req);
- }
- case WalletApiOperation.StartRefundQueryForUri: {
- const req = codecForPrepareRefundRequest().decode(payload);
- return await startRefundQueryForUri(wex, req.talerRefundUri);
- }
- case WalletApiOperation.StartRefundQuery: {
- const req = codecForStartRefundQueryRequest().decode(payload);
- return handleStartRefundQuery(wex, req);
- }
- case WalletApiOperation.AddBackupProvider: {
- const req = codecForAddBackupProviderRequest().decode(payload);
- return await addBackupProvider(wex, req);
- }
- case WalletApiOperation.RunBackupCycle: {
- const req = codecForRunBackupCycle().decode(payload);
- return handleAddBackupProvider(wex, req);
- }
- case WalletApiOperation.RemoveBackupProvider: {
- const req = codecForRemoveBackupProvider().decode(payload);
+ },
+ },
+ [WalletApiOperation.TestingGetSampleTransactions]: {
+ codec: codecForEmptyObject(),
+ handler: handleTestingGetSampleTransactions,
+ },
+ [WalletApiOperation.StartRefundQueryForUri]: {
+ codec: codecForPrepareRefundRequest(),
+ handler: (wex, req) => startRefundQueryForUri(wex, req.talerRefundUri),
+ },
+ [WalletApiOperation.StartRefundQuery]: {
+ codec: codecForStartRefundQueryRequest(),
+ handler: handleStartRefundQuery,
+ },
+ [WalletApiOperation.AddBackupProvider]: {
+ codec: codecForAddBackupProviderRequest(),
+ handler: addBackupProvider,
+ },
+ [WalletApiOperation.RunBackupCycle]: {
+ codec: codecForRunBackupCycle(),
+ handler: async (wex, req) => {
+ await runBackupCycle(wex, req);
+ return {};
+ },
+ },
+ [WalletApiOperation.RemoveBackupProvider]: {
+ codec: codecForRemoveBackupProvider(),
+ handler: async (wex, req) => {
await removeBackupProvider(wex, req);
return {};
- }
- case WalletApiOperation.ExportBackupRecovery: {
- const resp = await getBackupRecovery(wex);
- return resp;
- }
- case WalletApiOperation.TestingWaitTransactionState: {
- const req = payload as TestingWaitTransactionRequest;
+ },
+ },
+ [WalletApiOperation.ExportBackupRecovery]: {
+ codec: codecForEmptyObject(),
+ handler: getBackupRecovery,
+ },
+ [WalletApiOperation.TestingWaitTransactionState]: {
+ codec: codecForAny(),
+ handler: async (wex, req) => {
await waitTransactionState(wex, req.transactionId, req.txState);
return {};
- }
- case WalletApiOperation.GetCurrencySpecification: {
- const req = codecForGetCurrencyInfoRequest().decode(payload);
- return handleGetCurrencySpecification(wex, req);
- }
- case WalletApiOperation.ImportBackupRecovery: {
- const req = codecForAny().decode(payload);
+ },
+ },
+ [WalletApiOperation.GetCurrencySpecification]: {
+ codec: codecForGetCurrencyInfoRequest(),
+ handler: handleGetCurrencySpecification,
+ },
+ [WalletApiOperation.ImportBackupRecovery]: {
+ codec: codecForAny(),
+ handler: async (wex, req) => {
await loadBackupRecovery(wex, req);
return {};
- }
- case WalletApiOperation.HintNetworkAvailability: {
- const req = codecForHintNetworkAvailabilityRequest().decode(payload);
- return await handleHintNetworkAvailability(wex, req);
- }
- case WalletApiOperation.ConvertDepositAmount: {
- const req = codecForConvertAmountRequest.decode(payload);
- return await convertDepositAmount(wex, req);
- }
- case WalletApiOperation.GetMaxDepositAmount: {
- const req = codecForGetAmountRequest.decode(payload);
- return await getMaxDepositAmount(wex, req);
- }
- case WalletApiOperation.ConvertPeerPushAmount: {
- const req = codecForConvertAmountRequest.decode(payload);
- return await convertPeerPushAmount(wex, req);
- }
- case WalletApiOperation.GetMaxPeerPushAmount: {
- const req = codecForGetAmountRequest.decode(payload);
- return await getMaxPeerPushAmount(wex, req);
- }
- case WalletApiOperation.ConvertWithdrawalAmount: {
- const req = codecForConvertAmountRequest.decode(payload);
- return await convertWithdrawalAmount(wex, req);
- }
- case WalletApiOperation.GetBackupInfo: {
- const resp = await getBackupInfo(wex);
- return resp;
- }
- case WalletApiOperation.PrepareDeposit: {
- const req = codecForPrepareDepositRequest().decode(payload);
- return await checkDepositGroup(wex, req);
- }
- case WalletApiOperation.GenerateDepositGroupTxId:
+ },
+ },
+ [WalletApiOperation.HintNetworkAvailability]: {
+ codec: codecForHintNetworkAvailabilityRequest(),
+ handler: handleHintNetworkAvailability,
+ },
+ [WalletApiOperation.ConvertDepositAmount]: {
+ codec: codecForConvertAmountRequest,
+ handler: convertDepositAmount,
+ },
+ [WalletApiOperation.GetMaxDepositAmount]: {
+ codec: codecForGetMaxDepositAmountRequest,
+ handler: getMaxDepositAmount,
+ },
+ [WalletApiOperation.GetMaxPeerPushDebitAmount]: {
+ codec: codecForGetMaxPeerPushDebitAmountRequest(),
+ handler: getMaxPeerPushDebitAmount,
+ },
+ [WalletApiOperation.GetBackupInfo]: {
+ codec: codecForEmptyObject(),
+ handler: getBackupInfo,
+ },
+ [WalletApiOperation.PrepareDeposit]: {
+ codec: codecForCheckDepositRequest(),
+ handler: checkDepositGroup,
+ },
+ [WalletApiOperation.CheckDeposit]: {
+ codec: codecForCheckDepositRequest(),
+ handler: checkDepositGroup,
+ },
+ [WalletApiOperation.GenerateDepositGroupTxId]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
return {
- transactionId: generateDepositGroupTxId(),
+ transactionId: generateDepositGroupTxId() as TransactionIdStr,
};
- case WalletApiOperation.CreateDepositGroup: {
- const req = codecForCreateDepositGroupRequest().decode(payload);
- return await createDepositGroup(wex, req);
- }
- case WalletApiOperation.DeleteTransaction: {
- const req = codecForDeleteTransactionRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.CreateDepositGroup]: {
+ codec: codecForCreateDepositGroupRequest(),
+ handler: createDepositGroup,
+ },
+ [WalletApiOperation.DeleteTransaction]: {
+ codec: codecForDeleteTransactionRequest(),
+ handler: async (wex, req) => {
await deleteTransaction(wex, req.transactionId);
return {};
- }
- case WalletApiOperation.RetryTransaction: {
- const req = codecForRetryTransactionRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.RetryTransaction]: {
+ codec: codecForRetryTransactionRequest(),
+ handler: async (wex, req) => {
await retryTransaction(wex, req.transactionId);
return {};
- }
- case WalletApiOperation.SetWalletDeviceId: {
- const req = codecForSetWalletDeviceIdRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.SetWalletDeviceId]: {
+ codec: codecForSetWalletDeviceIdRequest(),
+ handler: async (wex, req) => {
await setWalletDeviceId(wex, req.walletDeviceId);
return {};
- }
- case WalletApiOperation.TestCrypto: {
+ },
+ },
+ [WalletApiOperation.TestCrypto]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
return await wex.cryptoApi.hashString({ str: "hello world" });
- }
- case WalletApiOperation.ClearDb: {
+ },
+ },
+ [WalletApiOperation.ClearDb]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
await clearDatabase(wex.db.idbHandle());
wex.ws.clearAllCaches();
return {};
- }
- case WalletApiOperation.Recycle: {
+ },
+ },
+ [WalletApiOperation.Recycle]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
throw Error("not implemented");
- return {};
- }
- case WalletApiOperation.ExportDb: {
+ },
+ },
+ [WalletApiOperation.ExportDb]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
const dbDump = await exportDb(wex.ws.idb);
return dbDump;
- }
- case WalletApiOperation.GetDepositWireTypesForCurrency: {
- const req =
- codecForGetDepositWireTypesForCurrencyRequest().decode(payload);
- return handleGetDepositWireTypesForCurrency(wex, req);
- }
- case WalletApiOperation.ListGlobalCurrencyExchanges: {
- const req = codecForEmptyObject().decode(payload);
- return await handleListGlobalCurrencyExchanges(wex, req);
- }
- case WalletApiOperation.ListGlobalCurrencyAuditors: {
- const req = codecForEmptyObject().decode(payload);
- return await handleListGlobalCurrencyAuditors(wex, req);
- }
- case WalletApiOperation.AddGlobalCurrencyExchange: {
- const req = codecForAddGlobalCurrencyExchangeRequest().decode(payload);
- return handleAddGlobalCurrencyExchange(wex, req);
- }
- case WalletApiOperation.RemoveGlobalCurrencyExchange: {
- const req = codecForRemoveGlobalCurrencyExchangeRequest().decode(payload);
- return handleRemoveGlobalCurrencyExchange(wex, req);
- }
- case WalletApiOperation.AddGlobalCurrencyAuditor: {
- const req = codecForAddGlobalCurrencyAuditorRequest().decode(payload);
- return handleAddGlobalCurrencyAuditor(wex, req);
- }
- case WalletApiOperation.TestingWaitTasksDone: {
+ },
+ },
+ [WalletApiOperation.GetDepositWireTypesForCurrency]: {
+ codec: codecForGetDepositWireTypesForCurrencyRequest(),
+ handler: handleGetDepositWireTypesForCurrency,
+ },
+ [WalletApiOperation.ListGlobalCurrencyExchanges]: {
+ codec: codecForEmptyObject(),
+ handler: handleListGlobalCurrencyExchanges,
+ },
+ [WalletApiOperation.ListGlobalCurrencyAuditors]: {
+ codec: codecForEmptyObject(),
+ handler: handleListGlobalCurrencyAuditors,
+ },
+ [WalletApiOperation.AddGlobalCurrencyExchange]: {
+ codec: codecForAddGlobalCurrencyExchangeRequest(),
+ handler: handleAddGlobalCurrencyExchange,
+ },
+ [WalletApiOperation.RemoveGlobalCurrencyExchange]: {
+ codec: codecForRemoveGlobalCurrencyExchangeRequest(),
+ handler: handleRemoveGlobalCurrencyExchange,
+ },
+ [WalletApiOperation.AddGlobalCurrencyAuditor]: {
+ codec: codecForAddGlobalCurrencyAuditorRequest(),
+ handler: handleAddGlobalCurrencyAuditor,
+ },
+ [WalletApiOperation.TestingWaitTasksDone]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
await waitTasksDone(wex);
return {};
- }
- case WalletApiOperation.TestingResetAllRetries:
+ },
+ },
+ [WalletApiOperation.TestingResetAllRetries]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
await retryAll(wex);
return {};
- case WalletApiOperation.RemoveGlobalCurrencyAuditor: {
- const req = codecForRemoveGlobalCurrencyAuditorRequest().decode(payload);
- return await handleRemoveGlobalCurrencyAuditor(wex, req);
- }
- case WalletApiOperation.ImportDb: {
- const req = codecForImportDbRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.RemoveGlobalCurrencyAuditor]: {
+ codec: codecForRemoveGlobalCurrencyAuditorRequest(),
+ handler: handleRemoveGlobalCurrencyAuditor,
+ },
+ [WalletApiOperation.ImportDb]: {
+ codec: codecForImportDbRequest(),
+ handler: async (wex, req) => {
+ // FIXME: This should atomically re-materialize transactions!
await importDb(wex.db.idbHandle(), req.dump);
- return [];
- }
- case WalletApiOperation.CheckPeerPushDebit: {
- const req = codecForCheckPeerPushDebitRequest().decode(payload);
- return await checkPeerPushDebit(wex, req);
- }
- case WalletApiOperation.InitiatePeerPushDebit: {
- const req = codecForInitiatePeerPushDebitRequest().decode(payload);
- return await initiatePeerPushDebit(wex, req);
- }
- case WalletApiOperation.PreparePeerPushCredit: {
- const req = codecForPreparePeerPushCreditRequest().decode(payload);
- return await preparePeerPushCredit(wex, req);
- }
- case WalletApiOperation.ConfirmPeerPushCredit: {
- const req = codecForConfirmPeerPushPaymentRequest().decode(payload);
- return await confirmPeerPushCredit(wex, req);
- }
- case WalletApiOperation.CheckPeerPullCredit: {
- const req = codecForPreparePeerPullPaymentRequest().decode(payload);
- return await checkPeerPullPaymentInitiation(wex, req);
- }
- case WalletApiOperation.InitiatePeerPullCredit: {
- const req = codecForInitiatePeerPullPaymentRequest().decode(payload);
- return await initiatePeerPullPayment(wex, req);
- }
- case WalletApiOperation.PreparePeerPullDebit: {
- const req = codecForCheckPeerPullPaymentRequest().decode(payload);
- return await preparePeerPullDebit(wex, req);
- }
- case WalletApiOperation.ConfirmPeerPullDebit: {
- const req = codecForAcceptPeerPullPaymentRequest().decode(payload);
- return await confirmPeerPullDebit(wex, req);
- }
- case WalletApiOperation.ApplyDevExperiment: {
- const req = codecForApplyDevExperiment().decode(payload);
+ await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
+ await rematerializeTransactions(wex, tx);
+ });
+ return {};
+ },
+ },
+ [WalletApiOperation.CheckPeerPushDebit]: {
+ codec: codecForCheckPeerPushDebitRequest(),
+ handler: checkPeerPushDebit,
+ },
+ [WalletApiOperation.InitiatePeerPushDebit]: {
+ codec: codecForInitiatePeerPushDebitRequest(),
+ handler: initiatePeerPushDebit,
+ },
+ [WalletApiOperation.PreparePeerPushCredit]: {
+ codec: codecForPreparePeerPushCreditRequest(),
+ handler: preparePeerPushCredit,
+ },
+ [WalletApiOperation.ConfirmPeerPushCredit]: {
+ codec: codecForConfirmPeerPushPaymentRequest(),
+ handler: confirmPeerPushCredit,
+ },
+ [WalletApiOperation.CheckPeerPullCredit]: {
+ codec: codecForPreparePeerPullPaymentRequest(),
+ handler: checkPeerPullCredit,
+ },
+ [WalletApiOperation.InitiatePeerPullCredit]: {
+ codec: codecForInitiatePeerPullPaymentRequest(),
+ handler: initiatePeerPullPayment,
+ },
+ [WalletApiOperation.PreparePeerPullDebit]: {
+ codec: codecForCheckPeerPullPaymentRequest(),
+ handler: preparePeerPullDebit,
+ },
+ [WalletApiOperation.ConfirmPeerPullDebit]: {
+ codec: codecForAcceptPeerPullPaymentRequest(),
+ handler: confirmPeerPullDebit,
+ },
+ [WalletApiOperation.ApplyDevExperiment]: {
+ codec: codecForApplyDevExperiment(),
+ handler: async (wex, req) => {
await applyDevExperiment(wex, req.devExperimentUri);
return {};
- }
- case WalletApiOperation.Shutdown: {
- const req = codecForEmptyObject().decode(payload);
- return await handleShutdown(wex, req);
- }
- case WalletApiOperation.GetVersion: {
- return handleGetVersion(wex);
- }
- case WalletApiOperation.TestingWaitTransactionsFinal:
- return await waitUntilAllTransactionsFinal(wex);
- case WalletApiOperation.TestingWaitRefreshesFinal:
- return await waitUntilRefreshesDone(wex);
- case WalletApiOperation.TestingSetTimetravel: {
- const req = codecForTestingSetTimetravelRequest().decode(payload);
- return await handleTestingSetTimetravel(wex, req);
- }
- case WalletApiOperation.DeleteExchange: {
- const req = codecForDeleteExchangeRequest().decode(payload);
- return await handleDeleteExchange(wex, req);
- }
- case WalletApiOperation.GetExchangeResources: {
- const req = codecForGetExchangeResourcesRequest().decode(payload);
+ },
+ },
+ [WalletApiOperation.Shutdown]: {
+ codec: codecForEmptyObject(),
+ handler: handleShutdown,
+ },
+ [WalletApiOperation.GetVersion]: {
+ codec: codecForEmptyObject(),
+ handler: handleGetVersion,
+ },
+ [WalletApiOperation.TestingWaitTransactionsFinal]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
+ await waitUntilAllTransactionsFinal(wex);
+ return {};
+ },
+ },
+ [WalletApiOperation.TestingWaitRefreshesFinal]: {
+ codec: codecForEmptyObject(),
+ handler: async (wex, req) => {
+ await waitUntilRefreshesDone(wex);
+ return {};
+ },
+ },
+ [WalletApiOperation.TestingSetTimetravel]: {
+ codec: codecForTestingSetTimetravelRequest(),
+ handler: async (wex, req) => {
+ await handleTestingSetTimetravel(wex, req);
+ return {};
+ },
+ },
+ [WalletApiOperation.DeleteExchange]: {
+ codec: codecForDeleteExchangeRequest(),
+ handler: handleDeleteExchange,
+ },
+ [WalletApiOperation.GetExchangeResources]: {
+ codec: codecForGetExchangeResourcesRequest(),
+ handler: async (wex, req) => {
return await getExchangeResources(wex, req.exchangeBaseUrl);
- }
- case WalletApiOperation.CanonicalizeBaseUrl: {
- const req = codecForCanonicalizeBaseUrlRequest().decode(payload);
- return handleCanonicalizeBaseUrl(wex, req);
- }
- }
- throw TalerError.fromDetail(
- TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN,
- {
- operation,
},
- "unknown operation",
- );
-}
-
-export async function handleGetCurrencySpecification(
- wex: WalletExecutionContext,
- req: GetCurrencySpecificationRequest,
-): Promise<GetCurrencySpecificationResponse> {
- const spec = await wex.db.runReadOnlyTx(
- {
- storeNames: ["currencyInfo"],
+ },
+ [WalletApiOperation.CanonicalizeBaseUrl]: {
+ codec: codecForCanonicalizeBaseUrlRequest(),
+ handler: handleCanonicalizeBaseUrl,
+ },
+ [WalletApiOperation.ForceRefresh]: {
+ codec: codecForForceRefreshRequest(),
+ handler: async (wex, req) => {
+ await forceRefresh(wex, req);
+ return {};
},
- async (tx) => {
- return WalletDbHelpers.getCurrencyInfo(tx, req.scope);
+ },
+ [WalletApiOperation.ExportBackup]: {
+ codec: codecForAny(),
+ handler: async (wex, req) => {
+ throw Error("not implemented");
},
- );
- if (spec) {
- return {
- currencySpecification: spec.currencySpec,
- };
+ },
+ [WalletApiOperation.ListAssociatedRefreshes]: {
+ codec: codecForAny(),
+ handler: async (wex, req) => {
+ throw Error("not implemented");
+ },
+ },
+ [WalletApiOperation.GetBankingChoicesForPayto]: {
+ codec: codecForGetBankingChoicesForPaytoRequest(),
+ handler: handleGetBankingChoicesForPayto,
+ },
+ [WalletApiOperation.StartExchangeWalletKyc]: {
+ codec: codecForStartExchangeWalletKycRequest(),
+ handler: handleStartExchangeWalletKyc,
+ },
+ [WalletApiOperation.TestingWaitExchangeWalletKyc]: {
+ codec: codecForTestingWaitWalletKycRequest(),
+ handler: handleTestingWaitExchangeWalletKyc,
+ },
+};
+
+/**
+ * Implementation of the "wallet-core" API.
+ */
+async function dispatchRequestInternal(
+ wex: WalletExecutionContext,
+ operation: WalletApiOperation,
+ payload: unknown,
+): Promise<WalletCoreResponseType<typeof operation>> {
+ if (!wex.ws.initCalled && operation !== WalletApiOperation.InitWallet) {
+ throw Error(
+ `wallet must be initialized before running operation ${operation}`,
+ );
}
- // Hard-coded mock for KUDOS and TESTKUDOS
- if (req.scope.currency === "KUDOS") {
- const kudosResp: GetCurrencySpecificationResponse = {
- currencySpecification: {
- name: "Kudos (Taler Demonstrator)",
- num_fractional_input_digits: 2,
- num_fractional_normal_digits: 2,
- num_fractional_trailing_zero_digits: 2,
- alt_unit_names: {
- "0": "ク",
- },
- },
- };
- return kudosResp;
- } else if (req.scope.currency === "TESTKUDOS") {
- const testkudosResp: GetCurrencySpecificationResponse = {
- currencySpecification: {
- name: "Test (Taler Unstable Demonstrator)",
- num_fractional_input_digits: 0,
- num_fractional_normal_digits: 0,
- num_fractional_trailing_zero_digits: 0,
- alt_unit_names: {
- "0": "テ",
- },
+
+ const h: HandlerWithValidator<any> = handlers[operation];
+
+ if (!h) {
+ throw TalerError.fromDetail(
+ TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN,
+ {
+ operation,
},
- };
- return testkudosResp;
+ "unknown operation",
+ );
}
- const defaultResp: GetCurrencySpecificationResponse = {
- currencySpecification: {
- name: req.scope.currency,
- num_fractional_input_digits: 2,
- num_fractional_normal_digits: 2,
- num_fractional_trailing_zero_digits: 2,
- alt_unit_names: {
- "0": req.scope.currency,
- },
- },
- };
- return defaultResp;
-}
-function handleGetVersion(wex: WalletExecutionContext): WalletCoreVersion {
- const result: WalletCoreVersion = {
- implementationSemver: walletCoreBuildInfo.implementationSemver,
- implementationGitHash: walletCoreBuildInfo.implementationGitHash,
- hash: undefined,
- version: WALLET_CORE_API_PROTOCOL_VERSION,
- exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
- merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
- bankConversionApiRange: WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION,
- bankIntegrationApiRange: TalerBankIntegrationHttpClient.PROTOCOL_VERSION,
- corebankApiRange: WALLET_COREBANK_API_PROTOCOL_VERSION,
- bank: TalerBankIntegrationHttpClient.PROTOCOL_VERSION,
- devMode: wex.ws.config.testing.devModeActive,
- };
- return result;
+ const req = h.codec.decode(payload);
+ return await h.handler(wex, req);
}
export function getObservedWalletExecutionContext(
ws: InternalWalletState,
cancellationToken: CancellationToken,
+ cts: CancellationToken.Source | undefined,
oc: ObservabilityContext,
): WalletExecutionContext {
const db = ws.createDbAccessHandle(cancellationToken);
const wex: WalletExecutionContext = {
ws,
cancellationToken,
+ cts,
cryptoApi: observeTalerCrypto(ws.cryptoApi, oc),
db: new ObservableDbAccess(db, oc),
http: new ObservableHttpClientLibrary(ws.http, oc),
@@ -2052,12 +2202,14 @@ export function getObservedWalletExecutionContext(
export function getNormalWalletExecutionContext(
ws: InternalWalletState,
cancellationToken: CancellationToken,
+ cts: CancellationToken.Source | undefined,
oc: ObservabilityContext,
): WalletExecutionContext {
const db = ws.createDbAccessHandle(cancellationToken);
const wex: WalletExecutionContext = {
ws,
cancellationToken,
+ cts,
cryptoApi: ws.cryptoApi,
db,
get http() {
@@ -2075,7 +2227,7 @@ export function getNormalWalletExecutionContext(
/**
* Handle a request to the wallet-core API.
*/
-async function handleCoreApiRequest(
+async function dispatchWalletCoreApiRequest(
ws: InternalWalletState,
operation: string,
id: string,
@@ -2106,12 +2258,12 @@ async function handleCoreApiRequest(
},
};
- wex = getObservedWalletExecutionContext(ws, cts.token, oc);
+ wex = getObservedWalletExecutionContext(ws, cts.token, cts, oc);
} else {
oc = {
observe(evt) {},
};
- wex = getNormalWalletExecutionContext(ws, cts.token, oc);
+ wex = getNormalWalletExecutionContext(ws, cts.token, cts, oc);
}
try {
@@ -2122,7 +2274,6 @@ async function handleCoreApiRequest(
});
const result = await dispatchRequestInternal(
wex,
- cts,
operation as any,
payload,
);
@@ -2154,9 +2305,7 @@ async function handleCoreApiRequest(
}
}
-export function applyRunConfigDefaults(
- wcp?: PartialWalletRunConfig,
-): WalletRunConfig {
+function applyRunConfigDefaults(wcp?: PartialWalletRunConfig): WalletRunConfig {
return {
builtin: {
exchanges: wcp?.builtin?.exchanges ?? [
@@ -2232,7 +2381,7 @@ export class Wallet {
payload: unknown,
): Promise<CoreApiResponse> {
await this.ws.ensureWalletDbOpen();
- return handleCoreApiRequest(this.ws, operation, id, payload);
+ return dispatchWalletCoreApiRequest(this.ws, operation, id, payload);
}
}