fix #7704
This commit is contained in:
parent
7330f0daf9
commit
d483a3f557
@ -725,6 +725,9 @@ export interface WalletCoreVersion {
|
|||||||
exchange: string;
|
exchange: string;
|
||||||
merchant: string;
|
merchant: string;
|
||||||
bank: string;
|
bank: string;
|
||||||
|
/**
|
||||||
|
* @deprecated will be removed
|
||||||
|
*/
|
||||||
devMode: boolean;
|
devMode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2157,15 +2160,6 @@ export interface ConfirmPeerPullDebitRequest {
|
|||||||
peerPullPaymentIncomingId: string;
|
peerPullPaymentIncomingId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SetDevModeRequest {
|
|
||||||
devModeEnabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const codecForSetDevModeRequest = (): Codec<SetDevModeRequest> =>
|
|
||||||
buildCodecForObject<SetDevModeRequest>()
|
|
||||||
.property("devModeEnabled", codecForBoolean())
|
|
||||||
.build("SetDevModeRequest");
|
|
||||||
|
|
||||||
export interface ApplyDevExperimentRequest {
|
export interface ApplyDevExperimentRequest {
|
||||||
devExperimentUri: string;
|
devExperimentUri: string;
|
||||||
}
|
}
|
||||||
|
@ -27,25 +27,18 @@ import {
|
|||||||
CoreApiResponse,
|
CoreApiResponse,
|
||||||
Duration,
|
Duration,
|
||||||
encodeCrock,
|
encodeCrock,
|
||||||
ExtendedStatus,
|
|
||||||
getErrorDetailFromException,
|
getErrorDetailFromException,
|
||||||
getRandomBytes,
|
getRandomBytes,
|
||||||
j2s,
|
j2s,
|
||||||
Logger,
|
Logger,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
PaymentStatus,
|
|
||||||
PreparePayResultType,
|
PreparePayResultType,
|
||||||
RecoveryMergeStrategy,
|
RecoveryMergeStrategy,
|
||||||
RefreshReason,
|
|
||||||
sampleWalletCoreTransactions,
|
sampleWalletCoreTransactions,
|
||||||
setDangerousTimetravel,
|
setDangerousTimetravel,
|
||||||
setGlobalLogLevelFromString,
|
setGlobalLogLevelFromString,
|
||||||
summarizeTalerErrorDetail,
|
summarizeTalerErrorDetail,
|
||||||
TalerUriType,
|
TalerUriType,
|
||||||
Transaction,
|
|
||||||
TransactionState,
|
|
||||||
TransactionSubstate,
|
|
||||||
TransactionType,
|
|
||||||
WalletNotification,
|
WalletNotification,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { clk } from "@gnu-taler/taler-util/clk";
|
import { clk } from "@gnu-taler/taler-util/clk";
|
||||||
@ -61,15 +54,9 @@ import { JsonMessage, runRpcServer } from "@gnu-taler/taler-util/twrpc";
|
|||||||
import {
|
import {
|
||||||
createNativeWalletHost,
|
createNativeWalletHost,
|
||||||
createNativeWalletHost2,
|
createNativeWalletHost2,
|
||||||
CryptoDispatcher,
|
|
||||||
nativeCrypto,
|
|
||||||
//NodeThreadCryptoWorkerFactory,
|
|
||||||
//SynchronousCryptoWorkerFactoryPlain,
|
|
||||||
TalerCryptoInterface,
|
|
||||||
Wallet,
|
Wallet,
|
||||||
WalletApiOperation,
|
WalletApiOperation,
|
||||||
WalletCoreApiClient,
|
WalletCoreApiClient,
|
||||||
walletCoreDebugFlags,
|
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import {
|
import {
|
||||||
createRemoteWallet,
|
createRemoteWallet,
|
||||||
@ -264,12 +251,19 @@ async function createLocalWallet(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any,
|
cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any,
|
||||||
|
config: {
|
||||||
|
features: {
|
||||||
|
batchWithdrawal: checkEnvFlag("TALER_WALLET_BATCH_WITHDRAWAL"),
|
||||||
|
},
|
||||||
|
testing: {
|
||||||
|
devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"),
|
||||||
|
denomselAllowLate: checkEnvFlag(
|
||||||
|
"TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (checkEnvFlag("TALER_WALLET_BATCH_WITHDRAWAL")) {
|
|
||||||
wallet.setBatchWithdrawal(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
applyVerbose(walletCliArgs.wallet.verbose);
|
applyVerbose(walletCliArgs.wallet.verbose);
|
||||||
try {
|
try {
|
||||||
await wallet.handleCoreApiRequest("initWallet", "native-init", {
|
await wallet.handleCoreApiRequest("initWallet", "native-init", {
|
||||||
@ -1405,30 +1399,6 @@ advancedCli
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
advancedCli
|
|
||||||
.subcommand("enableDevMode", "enable-dev-mode", {
|
|
||||||
help: "Enable developer mode (dangerous!)",
|
|
||||||
})
|
|
||||||
.action(async (args) => {
|
|
||||||
await withWallet(args, async (wallet) => {
|
|
||||||
await wallet.client.call(WalletApiOperation.SetDevMode, {
|
|
||||||
devModeEnabled: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
advancedCli
|
|
||||||
.subcommand("disableDevMode", "disable-dev-mode", {
|
|
||||||
help: "Disable developer mode",
|
|
||||||
})
|
|
||||||
.action(async (args) => {
|
|
||||||
await withWallet(args, async (wallet) => {
|
|
||||||
await wallet.client.call(WalletApiOperation.SetDevMode, {
|
|
||||||
devModeEnabled: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const coinPubListCodec = codecForList(codecForString());
|
const coinPubListCodec = codecForList(codecForString());
|
||||||
|
|
||||||
advancedCli
|
advancedCli
|
||||||
@ -1647,35 +1617,6 @@ async function read(stream: NodeJS.ReadStream) {
|
|||||||
return Buffer.concat(chunks).toString("utf8");
|
return Buffer.concat(chunks).toString("utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
// testCli
|
|
||||||
// .subcommand("cryptoworker", "cryptoworker")
|
|
||||||
// .maybeOption("impl", ["--impl"], clk.STRING)
|
|
||||||
// .action(async (args) => {
|
|
||||||
// let cryptoApi: TalerCryptoInterface;
|
|
||||||
// if (!args.cryptoworker.impl || args.cryptoworker.impl === "node") {
|
|
||||||
// const workerFactory = new NodeThreadCryptoWorkerFactory();
|
|
||||||
// const cryptoDisp = new CryptoDispatcher(workerFactory);
|
|
||||||
// cryptoApi = cryptoDisp.cryptoApi;
|
|
||||||
// } else if (args.cryptoworker.impl === "sync") {
|
|
||||||
// const workerFactory = new SynchronousCryptoWorkerFactoryPlain();
|
|
||||||
// const cryptoDisp = new CryptoDispatcher(workerFactory);
|
|
||||||
// cryptoApi = cryptoDisp.cryptoApi;
|
|
||||||
// } else if (args.cryptoworker.impl === "none") {
|
|
||||||
// cryptoApi = nativeCrypto;
|
|
||||||
// } else {
|
|
||||||
// throw Error(`invalid crypto worker type ${args.cryptoworker.impl}`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const input = "foo";
|
|
||||||
// console.log(`testing crypto worker by hashing string '${input}'`);
|
|
||||||
// const res = await cryptoApi.hashString({ str: input });
|
|
||||||
// console.log(res);
|
|
||||||
// });
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
if (getenv("TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE")) {
|
|
||||||
logger.warn("Allowing withdrawal of late denominations for debugging");
|
|
||||||
walletCoreDebugFlags.denomselAllowLate = true;
|
|
||||||
}
|
|
||||||
walletCli.run();
|
walletCli.run();
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ import {
|
|||||||
} from "./operations/withdraw.js";
|
} from "./operations/withdraw.js";
|
||||||
import { ExchangeInfo } from "./operations/exchanges.js";
|
import { ExchangeInfo } from "./operations/exchanges.js";
|
||||||
import { assembleRefreshRevealRequest } from "./operations/refresh.js";
|
import { assembleRefreshRevealRequest } from "./operations/refresh.js";
|
||||||
import { isWithdrawableDenom } from "./index.js";
|
import { isWithdrawableDenom, WalletConfig } from "./index.js";
|
||||||
|
|
||||||
const logger = new Logger("dbless.ts");
|
const logger = new Logger("dbless.ts");
|
||||||
|
|
||||||
@ -206,6 +206,7 @@ export async function withdrawCoin(args: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function findDenomOrThrow(
|
export function findDenomOrThrow(
|
||||||
|
denomselAllowLate: boolean,
|
||||||
exchangeInfo: ExchangeInfo,
|
exchangeInfo: ExchangeInfo,
|
||||||
amount: AmountString,
|
amount: AmountString,
|
||||||
): DenominationRecord {
|
): DenominationRecord {
|
||||||
@ -215,7 +216,10 @@ export function findDenomOrThrow(
|
|||||||
fraction: d.amountFrac,
|
fraction: d.amountFrac,
|
||||||
value: d.amountVal,
|
value: d.amountVal,
|
||||||
};
|
};
|
||||||
if (Amounts.cmp(value, amount) === 0 && isWithdrawableDenom(d)) {
|
if (
|
||||||
|
Amounts.cmp(value, amount) === 0 &&
|
||||||
|
isWithdrawableDenom(d, denomselAllowLate)
|
||||||
|
) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,35 +36,6 @@ import {
|
|||||||
|
|
||||||
const logger = new Logger("dev-experiments.ts");
|
const logger = new Logger("dev-experiments.ts");
|
||||||
|
|
||||||
export async function setDevMode(
|
|
||||||
ws: InternalWalletState,
|
|
||||||
enabled: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
if (enabled) {
|
|
||||||
logger.info("enabling devmode");
|
|
||||||
await ws.db
|
|
||||||
.mktx((x) => [x.config])
|
|
||||||
.runReadWrite(async (tx) => {
|
|
||||||
tx.config.put({
|
|
||||||
key: ConfigRecordKey.DevMode,
|
|
||||||
value: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
await maybeInitDevMode(ws);
|
|
||||||
} else {
|
|
||||||
logger.info("disabling devmode");
|
|
||||||
await ws.db
|
|
||||||
.mktx((x) => [x.config])
|
|
||||||
.runReadWrite(async (tx) => {
|
|
||||||
tx.config.put({
|
|
||||||
key: ConfigRecordKey.DevMode,
|
|
||||||
value: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
await leaveDevMode(ws);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a dev experiment to the wallet database / state.
|
* Apply a dev experiment to the wallet database / state.
|
||||||
*/
|
*/
|
||||||
@ -78,7 +49,7 @@ export async function applyDevExperiment(
|
|||||||
logger.info("unable to parse dev experiment URI");
|
logger.info("unable to parse dev experiment URI");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!ws.devModeActive) {
|
if (!ws.config.testing.devModeActive) {
|
||||||
throw Error(
|
throw Error(
|
||||||
"can't handle devmode URI (other than enable-devmode) unless devmode is active",
|
"can't handle devmode URI (other than enable-devmode) unless devmode is active",
|
||||||
);
|
);
|
||||||
@ -86,37 +57,6 @@ export async function applyDevExperiment(
|
|||||||
throw Error(`dev-experiment id not understood ${parsedUri.devExperimentId}`);
|
throw Error(`dev-experiment id not understood ${parsedUri.devExperimentId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enter dev mode, if the wallet's config entry in the DB demands it.
|
|
||||||
*/
|
|
||||||
export async function maybeInitDevMode(ws: InternalWalletState): Promise<void> {
|
|
||||||
const devMode = await ws.db
|
|
||||||
.mktx((x) => [x.config])
|
|
||||||
.runReadOnly(async (tx) => {
|
|
||||||
const rec = await tx.config.get(ConfigRecordKey.DevMode);
|
|
||||||
if (!rec || rec.key !== ConfigRecordKey.DevMode) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return rec.value;
|
|
||||||
});
|
|
||||||
if (!devMode) {
|
|
||||||
ws.devModeActive = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ws.devModeActive = true;
|
|
||||||
if (ws.http instanceof DevExperimentHttpLib) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ws.http = new DevExperimentHttpLib(ws.http);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function leaveDevMode(ws: InternalWalletState): Promise<void> {
|
|
||||||
if (ws.http instanceof DevExperimentHttpLib) {
|
|
||||||
ws.http = ws.http.underlyingLib;
|
|
||||||
}
|
|
||||||
ws.devModeActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DevExperimentHttpLib implements HttpRequestLibrary {
|
export class DevExperimentHttpLib implements HttpRequestLibrary {
|
||||||
_isDevExperimentLib = true;
|
_isDevExperimentLib = true;
|
||||||
underlyingLib: HttpRequestLibrary;
|
underlyingLib: HttpRequestLibrary;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import { WalletNotification } from "@gnu-taler/taler-util";
|
import { WalletNotification } from "@gnu-taler/taler-util";
|
||||||
import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
|
import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
|
||||||
|
import { WalletConfig, WalletConfigParameter } from "./index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helpers to initiate a wallet in a host environment.
|
* Helpers to initiate a wallet in a host environment.
|
||||||
@ -44,6 +45,11 @@ export interface DefaultNodeWalletArgs {
|
|||||||
httpLib?: HttpRequestLibrary;
|
httpLib?: HttpRequestLibrary;
|
||||||
|
|
||||||
cryptoWorkerType?: "sync" | "node-worker-thread";
|
cryptoWorkerType?: "sync" | "node-worker-thread";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config parameters
|
||||||
|
*/
|
||||||
|
config?: WalletConfigParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,7 +144,13 @@ export async function createNativeWalletHost2(
|
|||||||
|
|
||||||
const timer = new SetTimeoutTimerAPI();
|
const timer = new SetTimeoutTimerAPI();
|
||||||
|
|
||||||
const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
|
const w = await Wallet.create(
|
||||||
|
myDb,
|
||||||
|
myHttpLib,
|
||||||
|
timer,
|
||||||
|
workerFactory,
|
||||||
|
args.config,
|
||||||
|
);
|
||||||
|
|
||||||
if (args.notifyHandler) {
|
if (args.notifyHandler) {
|
||||||
w.addNotificationListener(args.notifyHandler);
|
w.addNotificationListener(args.notifyHandler);
|
||||||
|
@ -108,7 +108,13 @@ export async function createNativeWalletHost2(
|
|||||||
|
|
||||||
const timer = new SetTimeoutTimerAPI();
|
const timer = new SetTimeoutTimerAPI();
|
||||||
|
|
||||||
const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
|
const w = await Wallet.create(
|
||||||
|
myDb,
|
||||||
|
myHttpLib,
|
||||||
|
timer,
|
||||||
|
workerFactory,
|
||||||
|
args.config,
|
||||||
|
);
|
||||||
|
|
||||||
if (args.notifyHandler) {
|
if (args.notifyHandler) {
|
||||||
w.addNotificationListener(args.notifyHandler);
|
w.addNotificationListener(args.notifyHandler);
|
||||||
|
@ -36,7 +36,6 @@ export {
|
|||||||
|
|
||||||
export * from "./pending-types.js";
|
export * from "./pending-types.js";
|
||||||
|
|
||||||
export * from "./util/debugFlags.js";
|
|
||||||
export { InternalWalletState } from "./internal-wallet-state.js";
|
export { InternalWalletState } from "./internal-wallet-state.js";
|
||||||
export * from "./wallet-api-types.js";
|
export * from "./wallet-api-types.js";
|
||||||
export * from "./wallet.js";
|
export * from "./wallet.js";
|
||||||
|
@ -52,6 +52,7 @@ import {
|
|||||||
GetReadWriteAccess,
|
GetReadWriteAccess,
|
||||||
} from "./util/query.js";
|
} from "./util/query.js";
|
||||||
import { TimerGroup } from "./util/timer.js";
|
import { TimerGroup } from "./util/timer.js";
|
||||||
|
import { WalletConfig } from "./wallet-api-types.js";
|
||||||
|
|
||||||
export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
|
export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
|
||||||
export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
|
export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
|
||||||
@ -168,9 +169,7 @@ export interface InternalWalletState {
|
|||||||
timerGroup: TimerGroup;
|
timerGroup: TimerGroup;
|
||||||
stopped: boolean;
|
stopped: boolean;
|
||||||
|
|
||||||
insecureTrustExchange: boolean;
|
config: Readonly<WalletConfig>;
|
||||||
|
|
||||||
batchWithdrawal: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous condition to interrupt the sleep of the
|
* Asynchronous condition to interrupt the sleep of the
|
||||||
@ -191,8 +190,6 @@ export interface InternalWalletState {
|
|||||||
merchantOps: MerchantOperations;
|
merchantOps: MerchantOperations;
|
||||||
refreshOps: RefreshOperations;
|
refreshOps: RefreshOperations;
|
||||||
|
|
||||||
devModeActive: boolean;
|
|
||||||
|
|
||||||
getDenomInfo(
|
getDenomInfo(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
tx: GetReadOnlyAccess<{
|
tx: GetReadOnlyAccess<{
|
||||||
|
@ -840,7 +840,12 @@ export async function getTotalFeesForDepositAmount(
|
|||||||
denom.value,
|
denom.value,
|
||||||
pcs.coinContributions[i],
|
pcs.coinContributions[i],
|
||||||
).amount;
|
).amount;
|
||||||
const refreshCost = getTotalRefreshCost(allDenoms, denom, amountLeft);
|
const refreshCost = getTotalRefreshCost(
|
||||||
|
allDenoms,
|
||||||
|
denom,
|
||||||
|
amountLeft,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
|
);
|
||||||
refreshFee.push(refreshCost);
|
refreshFee.push(refreshCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ async function validateWireInfo(
|
|||||||
for (const a of wireInfo.accounts) {
|
for (const a of wireInfo.accounts) {
|
||||||
logger.trace("validating exchange acct");
|
logger.trace("validating exchange acct");
|
||||||
let isValid = false;
|
let isValid = false;
|
||||||
if (ws.insecureTrustExchange) {
|
if (ws.config.testing.insecureTrustExchange) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else {
|
} else {
|
||||||
const { valid: v } = await ws.cryptoApi.isValidWireAccount({
|
const { valid: v } = await ws.cryptoApi.isValidWireAccount({
|
||||||
@ -275,7 +275,7 @@ async function validateWireInfo(
|
|||||||
wireFee: Amounts.stringify(x.wire_fee),
|
wireFee: Amounts.stringify(x.wire_fee),
|
||||||
};
|
};
|
||||||
let isValid = false;
|
let isValid = false;
|
||||||
if (ws.insecureTrustExchange) {
|
if (ws.config.testing.insecureTrustExchange) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else {
|
} else {
|
||||||
const { valid: v } = await ws.cryptoApi.isValidWireFee({
|
const { valid: v } = await ws.cryptoApi.isValidWireFee({
|
||||||
@ -308,7 +308,7 @@ async function validateGlobalFees(
|
|||||||
for (const gf of fees) {
|
for (const gf of fees) {
|
||||||
logger.trace("validating exchange global fees");
|
logger.trace("validating exchange global fees");
|
||||||
let isValid = false;
|
let isValid = false;
|
||||||
if (ws.insecureTrustExchange) {
|
if (ws.config.testing.insecureTrustExchange) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else {
|
} else {
|
||||||
const { valid: v } = await ws.cryptoApi.isValidGlobalFees({
|
const { valid: v } = await ws.cryptoApi.isValidGlobalFees({
|
||||||
@ -665,7 +665,10 @@ export async function updateExchangeFromUrlHandler(
|
|||||||
|
|
||||||
let ageMask = 0;
|
let ageMask = 0;
|
||||||
for (const x of keysInfo.currentDenominations) {
|
for (const x of keysInfo.currentDenominations) {
|
||||||
if (isWithdrawableDenom(x) && x.denomPub.age_mask != 0) {
|
if (
|
||||||
|
isWithdrawableDenom(x, ws.config.testing.denomselAllowLate) &&
|
||||||
|
x.denomPub.age_mask != 0
|
||||||
|
) {
|
||||||
ageMask = x.denomPub.age_mask;
|
ageMask = x.denomPub.age_mask;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,6 +168,7 @@ export async function getTotalPaymentCost(
|
|||||||
allDenoms,
|
allDenoms,
|
||||||
DenominationRecord.toDenomInfo(denom),
|
DenominationRecord.toDenomInfo(denom),
|
||||||
amountLeft,
|
amountLeft,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
|
costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
|
||||||
costs.push(refreshCost);
|
costs.push(refreshCost);
|
||||||
@ -1659,6 +1660,7 @@ async function applySuccessfulRefund(
|
|||||||
p: PurchaseRecord,
|
p: PurchaseRecord,
|
||||||
refreshCoinsMap: Record<string, CoinRefreshRequest>,
|
refreshCoinsMap: Record<string, CoinRefreshRequest>,
|
||||||
r: MerchantCoinRefundSuccessStatus,
|
r: MerchantCoinRefundSuccessStatus,
|
||||||
|
denomselAllowLate: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// FIXME: check signature before storing it as valid!
|
// FIXME: check signature before storing it as valid!
|
||||||
|
|
||||||
@ -1688,6 +1690,7 @@ async function applySuccessfulRefund(
|
|||||||
allDenoms,
|
allDenoms,
|
||||||
DenominationRecord.toDenomInfo(denom),
|
DenominationRecord.toDenomInfo(denom),
|
||||||
amountLeft,
|
amountLeft,
|
||||||
|
denomselAllowLate,
|
||||||
);
|
);
|
||||||
|
|
||||||
refreshCoinsMap[coin.coinPub] = {
|
refreshCoinsMap[coin.coinPub] = {
|
||||||
@ -1714,6 +1717,7 @@ async function storePendingRefund(
|
|||||||
}>,
|
}>,
|
||||||
p: PurchaseRecord,
|
p: PurchaseRecord,
|
||||||
r: MerchantCoinRefundFailureStatus,
|
r: MerchantCoinRefundFailureStatus,
|
||||||
|
denomselAllowLate: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const refundKey = getRefundKey(r);
|
const refundKey = getRefundKey(r);
|
||||||
|
|
||||||
@ -1745,6 +1749,7 @@ async function storePendingRefund(
|
|||||||
allDenoms,
|
allDenoms,
|
||||||
DenominationRecord.toDenomInfo(denom),
|
DenominationRecord.toDenomInfo(denom),
|
||||||
amountLeft,
|
amountLeft,
|
||||||
|
denomselAllowLate,
|
||||||
);
|
);
|
||||||
|
|
||||||
p.refunds[refundKey] = {
|
p.refunds[refundKey] = {
|
||||||
@ -1767,6 +1772,7 @@ async function storeFailedRefund(
|
|||||||
p: PurchaseRecord,
|
p: PurchaseRecord,
|
||||||
refreshCoinsMap: Record<string, CoinRefreshRequest>,
|
refreshCoinsMap: Record<string, CoinRefreshRequest>,
|
||||||
r: MerchantCoinRefundFailureStatus,
|
r: MerchantCoinRefundFailureStatus,
|
||||||
|
denomselAllowLate: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const refundKey = getRefundKey(r);
|
const refundKey = getRefundKey(r);
|
||||||
|
|
||||||
@ -1797,6 +1803,7 @@ async function storeFailedRefund(
|
|||||||
allDenoms,
|
allDenoms,
|
||||||
DenominationRecord.toDenomInfo(denom),
|
DenominationRecord.toDenomInfo(denom),
|
||||||
amountLeft,
|
amountLeft,
|
||||||
|
denomselAllowLate,
|
||||||
);
|
);
|
||||||
|
|
||||||
p.refunds[refundKey] = {
|
p.refunds[refundKey] = {
|
||||||
@ -1905,11 +1912,28 @@ async function acceptRefunds(
|
|||||||
// Invariant: (!existingRefundInfo) || (existingRefundInfo === Pending)
|
// Invariant: (!existingRefundInfo) || (existingRefundInfo === Pending)
|
||||||
|
|
||||||
if (refundStatus.type === "success") {
|
if (refundStatus.type === "success") {
|
||||||
await applySuccessfulRefund(tx, p, refreshCoinsMap, refundStatus);
|
await applySuccessfulRefund(
|
||||||
|
tx,
|
||||||
|
p,
|
||||||
|
refreshCoinsMap,
|
||||||
|
refundStatus,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
|
);
|
||||||
} else if (isPermanentFailure) {
|
} else if (isPermanentFailure) {
|
||||||
await storeFailedRefund(tx, p, refreshCoinsMap, refundStatus);
|
await storeFailedRefund(
|
||||||
|
tx,
|
||||||
|
p,
|
||||||
|
refreshCoinsMap,
|
||||||
|
refundStatus,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await storePendingRefund(tx, p, refundStatus);
|
await storePendingRefund(
|
||||||
|
tx,
|
||||||
|
p,
|
||||||
|
refundStatus,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,6 +417,7 @@ export async function getTotalPeerPaymentCost(
|
|||||||
allDenoms,
|
allDenoms,
|
||||||
DenominationRecord.toDenomInfo(denom),
|
DenominationRecord.toDenomInfo(denom),
|
||||||
amountLeft,
|
amountLeft,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
costs.push(Amounts.parseOrThrow(pcs[i].contribution));
|
costs.push(Amounts.parseOrThrow(pcs[i].contribution));
|
||||||
costs.push(refreshCost);
|
costs.push(refreshCost);
|
||||||
|
@ -86,7 +86,7 @@ import {
|
|||||||
import { makeCoinAvailable } from "./common.js";
|
import { makeCoinAvailable } from "./common.js";
|
||||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||||
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
|
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
|
||||||
import { isWithdrawableDenom } from "../index.js";
|
import { isWithdrawableDenom, WalletConfig } from "../index.js";
|
||||||
|
|
||||||
const logger = new Logger("refresh.ts");
|
const logger = new Logger("refresh.ts");
|
||||||
|
|
||||||
@ -105,13 +105,18 @@ export function getTotalRefreshCost(
|
|||||||
denoms: DenominationRecord[],
|
denoms: DenominationRecord[],
|
||||||
refreshedDenom: DenominationInfo,
|
refreshedDenom: DenominationInfo,
|
||||||
amountLeft: AmountJson,
|
amountLeft: AmountJson,
|
||||||
|
denomselAllowLate: boolean,
|
||||||
): AmountJson {
|
): AmountJson {
|
||||||
const withdrawAmount = Amounts.sub(
|
const withdrawAmount = Amounts.sub(
|
||||||
amountLeft,
|
amountLeft,
|
||||||
refreshedDenom.feeRefresh,
|
refreshedDenom.feeRefresh,
|
||||||
).amount;
|
).amount;
|
||||||
const denomMap = Object.fromEntries(denoms.map((x) => [x.denomPubHash, x]));
|
const denomMap = Object.fromEntries(denoms.map((x) => [x.denomPubHash, x]));
|
||||||
const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms);
|
const withdrawDenoms = selectWithdrawalDenominations(
|
||||||
|
withdrawAmount,
|
||||||
|
denoms,
|
||||||
|
denomselAllowLate,
|
||||||
|
);
|
||||||
const resultingAmount = Amounts.add(
|
const resultingAmount = Amounts.add(
|
||||||
Amounts.zeroOfCurrency(withdrawAmount.currency),
|
Amounts.zeroOfCurrency(withdrawAmount.currency),
|
||||||
...withdrawDenoms.selectedDenoms.map(
|
...withdrawDenoms.selectedDenoms.map(
|
||||||
@ -232,6 +237,7 @@ async function refreshCreateSession(
|
|||||||
const newCoinDenoms = selectWithdrawalDenominations(
|
const newCoinDenoms = selectWithdrawalDenominations(
|
||||||
availableAmount,
|
availableAmount,
|
||||||
availableDenoms,
|
availableDenoms,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newCoinDenoms.selectedDenoms.length === 0) {
|
if (newCoinDenoms.selectedDenoms.length === 0) {
|
||||||
@ -897,7 +903,7 @@ export async function createRefreshGroup(
|
|||||||
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
|
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
|
||||||
.iter(exchangeBaseUrl)
|
.iter(exchangeBaseUrl)
|
||||||
.filter((x) => {
|
.filter((x) => {
|
||||||
return isWithdrawableDenom(x);
|
return isWithdrawableDenom(x, ws.config.testing.denomselAllowLate);
|
||||||
});
|
});
|
||||||
denomsPerExchange[exchangeBaseUrl] = allDenoms;
|
denomsPerExchange[exchangeBaseUrl] = allDenoms;
|
||||||
return allDenoms;
|
return allDenoms;
|
||||||
@ -955,6 +961,7 @@ export async function createRefreshGroup(
|
|||||||
denoms,
|
denoms,
|
||||||
denom,
|
denom,
|
||||||
Amounts.parseOrThrow(refreshAmount),
|
Amounts.parseOrThrow(refreshAmount),
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
const output = Amounts.sub(refreshAmount, cost).amount;
|
const output = Amounts.sub(refreshAmount, cost).amount;
|
||||||
estimatedOutputPerCoin.push(output);
|
estimatedOutputPerCoin.push(output);
|
||||||
|
@ -210,7 +210,9 @@ export async function getCandidateWithdrawalDenoms(
|
|||||||
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
|
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
|
||||||
exchangeBaseUrl,
|
exchangeBaseUrl,
|
||||||
);
|
);
|
||||||
return allDenoms.filter(isWithdrawableDenom);
|
return allDenoms.filter((d) =>
|
||||||
|
isWithdrawableDenom(d, ws.config.testing.denomselAllowLate),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,7 +721,7 @@ export async function updateWithdrawalDenoms(
|
|||||||
}) signature of ${denom.denomPubHash}`,
|
}) signature of ${denom.denomPubHash}`,
|
||||||
);
|
);
|
||||||
let valid = false;
|
let valid = false;
|
||||||
if (ws.insecureTrustExchange) {
|
if (ws.config.testing.insecureTrustExchange) {
|
||||||
valid = true;
|
valid = true;
|
||||||
} else {
|
} else {
|
||||||
const res = await ws.cryptoApi.isValidDenom({
|
const res = await ws.cryptoApi.isValidDenom({
|
||||||
@ -1003,7 +1005,7 @@ export async function processWithdrawalGroup(
|
|||||||
const resp = await processPlanchetExchangeBatchRequest(ws, wgContext, {
|
const resp = await processPlanchetExchangeBatchRequest(ws, wgContext, {
|
||||||
batchSize: maxBatchSize,
|
batchSize: maxBatchSize,
|
||||||
coinStartIndex: i,
|
coinStartIndex: i,
|
||||||
useBatchRequest: ws.batchWithdrawal,
|
useBatchRequest: ws.config.features.batchWithdrawal,
|
||||||
});
|
});
|
||||||
let work: Promise<void>[] = [];
|
let work: Promise<void>[] = [];
|
||||||
work = [];
|
work = [];
|
||||||
@ -1180,6 +1182,7 @@ export async function getExchangeWithdrawalInfo(
|
|||||||
const selectedDenoms = selectWithdrawalDenominations(
|
const selectedDenoms = selectWithdrawalDenominations(
|
||||||
instructedAmount,
|
instructedAmount,
|
||||||
denoms,
|
denoms,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedDenoms.selectedDenoms.length === 0) {
|
if (selectedDenoms.selectedDenoms.length === 0) {
|
||||||
@ -1710,9 +1713,14 @@ export async function internalCreateWithdrawalGroup(
|
|||||||
amount,
|
amount,
|
||||||
denoms,
|
denoms,
|
||||||
args.forcedDenomSel,
|
args.forcedDenomSel,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
initialDenomSel = selectWithdrawalDenominations(amount, denoms);
|
initialDenomSel = selectWithdrawalDenominations(
|
||||||
|
amount,
|
||||||
|
denoms,
|
||||||
|
ws.config.testing.denomselAllowLate,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const withdrawalGroup: WithdrawalGroupRecord = {
|
const withdrawalGroup: WithdrawalGroupRecord = {
|
||||||
|
@ -48,7 +48,11 @@ import {
|
|||||||
AllowedExchangeInfo,
|
AllowedExchangeInfo,
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { getExchangeDetails, isWithdrawableDenom } from "../index.js";
|
import {
|
||||||
|
getExchangeDetails,
|
||||||
|
isWithdrawableDenom,
|
||||||
|
WalletConfig,
|
||||||
|
} from "../index.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { getMerchantPaymentBalanceDetails } from "../operations/balance.js";
|
import { getMerchantPaymentBalanceDetails } from "../operations/balance.js";
|
||||||
import { checkDbInvariant, checkLogicInvariant } from "./invariants.js";
|
import { checkDbInvariant, checkLogicInvariant } from "./invariants.js";
|
||||||
@ -664,6 +668,7 @@ export async function selectCandidates(
|
|||||||
export function selectWithdrawalDenominations(
|
export function selectWithdrawalDenominations(
|
||||||
amountAvailable: AmountJson,
|
amountAvailable: AmountJson,
|
||||||
denoms: DenominationRecord[],
|
denoms: DenominationRecord[],
|
||||||
|
denomselAllowLate: boolean = false,
|
||||||
): DenomSelectionState {
|
): DenomSelectionState {
|
||||||
let remaining = Amounts.copy(amountAvailable);
|
let remaining = Amounts.copy(amountAvailable);
|
||||||
|
|
||||||
@ -675,7 +680,7 @@ export function selectWithdrawalDenominations(
|
|||||||
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||||
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||||
|
|
||||||
denoms = denoms.filter(isWithdrawableDenom);
|
denoms = denoms.filter((d) => isWithdrawableDenom(d, denomselAllowLate));
|
||||||
denoms.sort((d1, d2) =>
|
denoms.sort((d1, d2) =>
|
||||||
Amounts.cmp(
|
Amounts.cmp(
|
||||||
DenominationRecord.getValue(d2),
|
DenominationRecord.getValue(d2),
|
||||||
@ -737,6 +742,7 @@ export function selectForcedWithdrawalDenominations(
|
|||||||
amountAvailable: AmountJson,
|
amountAvailable: AmountJson,
|
||||||
denoms: DenominationRecord[],
|
denoms: DenominationRecord[],
|
||||||
forcedDenomSel: ForcedDenomSel,
|
forcedDenomSel: ForcedDenomSel,
|
||||||
|
denomselAllowLate: boolean,
|
||||||
): DenomSelectionState {
|
): DenomSelectionState {
|
||||||
const selectedDenoms: {
|
const selectedDenoms: {
|
||||||
count: number;
|
count: number;
|
||||||
@ -746,7 +752,7 @@ export function selectForcedWithdrawalDenominations(
|
|||||||
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||||
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||||
|
|
||||||
denoms = denoms.filter(isWithdrawableDenom);
|
denoms = denoms.filter((d) => isWithdrawableDenom(d, denomselAllowLate));
|
||||||
denoms.sort((d1, d2) =>
|
denoms.sort((d1, d2) =>
|
||||||
Amounts.cmp(
|
Amounts.cmp(
|
||||||
DenominationRecord.getValue(d2),
|
DenominationRecord.getValue(d2),
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2021 Taler Systems S.A.
|
|
||||||
|
|
||||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Debug flags for wallet-core.
|
|
||||||
*
|
|
||||||
* @author Florian Dold
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface WalletCoreDebugFlags {
|
|
||||||
/**
|
|
||||||
* Allow withdrawal of denominations even though they are about to expire.
|
|
||||||
*/
|
|
||||||
denomselAllowLate: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const walletCoreDebugFlags: WalletCoreDebugFlags = {
|
|
||||||
denomselAllowLate: false,
|
|
||||||
};
|
|
@ -29,7 +29,7 @@ import {
|
|||||||
WireFee,
|
WireFee,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { DenominationRecord } from "../db.js";
|
import { DenominationRecord } from "../db.js";
|
||||||
import { walletCoreDebugFlags } from "./debugFlags.js";
|
import { WalletConfig } from "../index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of denominations with the same value and same period of time:
|
* Given a list of denominations with the same value and same period of time:
|
||||||
@ -452,13 +452,16 @@ export function createTimeline<Type extends object>(
|
|||||||
* Check if a denom is withdrawable based on the expiration time,
|
* Check if a denom is withdrawable based on the expiration time,
|
||||||
* revocation and offered state.
|
* revocation and offered state.
|
||||||
*/
|
*/
|
||||||
export function isWithdrawableDenom(d: DenominationRecord): boolean {
|
export function isWithdrawableDenom(
|
||||||
|
d: DenominationRecord,
|
||||||
|
denomselAllowLate?: boolean,
|
||||||
|
): boolean {
|
||||||
const now = AbsoluteTime.now();
|
const now = AbsoluteTime.now();
|
||||||
const start = AbsoluteTime.fromTimestamp(d.stampStart);
|
const start = AbsoluteTime.fromTimestamp(d.stampStart);
|
||||||
const withdrawExpire = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
|
const withdrawExpire = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
|
||||||
const started = AbsoluteTime.cmp(now, start) >= 0;
|
const started = AbsoluteTime.cmp(now, start) >= 0;
|
||||||
let lastPossibleWithdraw: AbsoluteTime;
|
let lastPossibleWithdraw: AbsoluteTime;
|
||||||
if (walletCoreDebugFlags.denomselAllowLate) {
|
if (denomselAllowLate) {
|
||||||
lastPossibleWithdraw = start;
|
lastPossibleWithdraw = start;
|
||||||
} else {
|
} else {
|
||||||
lastPossibleWithdraw = AbsoluteTime.subtractDuraction(
|
lastPossibleWithdraw = AbsoluteTime.subtractDuraction(
|
||||||
|
@ -29,8 +29,6 @@ import {
|
|||||||
AcceptExchangeTosRequest,
|
AcceptExchangeTosRequest,
|
||||||
AcceptManualWithdrawalRequest,
|
AcceptManualWithdrawalRequest,
|
||||||
AcceptManualWithdrawalResult,
|
AcceptManualWithdrawalResult,
|
||||||
ConfirmPeerPullDebitRequest,
|
|
||||||
ConfirmPeerPushCreditRequest,
|
|
||||||
AcceptTipRequest,
|
AcceptTipRequest,
|
||||||
AcceptTipResponse,
|
AcceptTipResponse,
|
||||||
AcceptWithdrawalResponse,
|
AcceptWithdrawalResponse,
|
||||||
@ -42,17 +40,18 @@ import {
|
|||||||
ApplyRefundResponse,
|
ApplyRefundResponse,
|
||||||
BackupRecovery,
|
BackupRecovery,
|
||||||
BalancesResponse,
|
BalancesResponse,
|
||||||
PreparePeerPullDebitRequest,
|
CheckPeerPullCreditRequest,
|
||||||
PreparePeerPullDebitResponse,
|
CheckPeerPullCreditResponse,
|
||||||
PreparePeerPushCredit,
|
CheckPeerPushDebitRequest,
|
||||||
PreparePeerPushCreditResponse,
|
CheckPeerPushDebitResponse,
|
||||||
CoinDumpJson,
|
CoinDumpJson,
|
||||||
ConfirmPayRequest,
|
ConfirmPayRequest,
|
||||||
ConfirmPayResult,
|
ConfirmPayResult,
|
||||||
|
ConfirmPeerPullDebitRequest,
|
||||||
|
ConfirmPeerPushCreditRequest,
|
||||||
CreateDepositGroupRequest,
|
CreateDepositGroupRequest,
|
||||||
CreateDepositGroupResponse,
|
CreateDepositGroupResponse,
|
||||||
DeleteTransactionRequest,
|
DeleteTransactionRequest,
|
||||||
DepositGroupFees,
|
|
||||||
ExchangeDetailedResponse,
|
ExchangeDetailedResponse,
|
||||||
ExchangesListResponse,
|
ExchangesListResponse,
|
||||||
ForceRefreshRequest,
|
ForceRefreshRequest,
|
||||||
@ -63,12 +62,12 @@ import {
|
|||||||
GetExchangeTosResult,
|
GetExchangeTosResult,
|
||||||
GetWithdrawalDetailsForAmountRequest,
|
GetWithdrawalDetailsForAmountRequest,
|
||||||
GetWithdrawalDetailsForUriRequest,
|
GetWithdrawalDetailsForUriRequest,
|
||||||
|
InitRequest,
|
||||||
|
InitResponse,
|
||||||
InitiatePeerPullCreditRequest,
|
InitiatePeerPullCreditRequest,
|
||||||
InitiatePeerPullCreditResponse,
|
InitiatePeerPullCreditResponse,
|
||||||
InitiatePeerPushPaymentRequest,
|
InitiatePeerPushPaymentRequest,
|
||||||
InitiatePeerPushPaymentResponse,
|
InitiatePeerPushPaymentResponse,
|
||||||
InitRequest,
|
|
||||||
InitResponse,
|
|
||||||
IntegrationTestArgs,
|
IntegrationTestArgs,
|
||||||
KnownBankAccounts,
|
KnownBankAccounts,
|
||||||
ListKnownBankAccountsRequest,
|
ListKnownBankAccountsRequest,
|
||||||
@ -78,10 +77,10 @@ import {
|
|||||||
PreparePayRequest,
|
PreparePayRequest,
|
||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
PreparePayTemplateRequest,
|
PreparePayTemplateRequest,
|
||||||
CheckPeerPullCreditRequest,
|
PreparePeerPullDebitRequest,
|
||||||
CheckPeerPullCreditResponse,
|
PreparePeerPullDebitResponse,
|
||||||
CheckPeerPushDebitRequest,
|
PreparePeerPushCredit,
|
||||||
CheckPeerPushDebitResponse,
|
PreparePeerPushCreditResponse,
|
||||||
PrepareRefundRequest,
|
PrepareRefundRequest,
|
||||||
PrepareRefundResult,
|
PrepareRefundResult,
|
||||||
PrepareTipRequest,
|
PrepareTipRequest,
|
||||||
@ -89,7 +88,6 @@ import {
|
|||||||
RecoveryLoadRequest,
|
RecoveryLoadRequest,
|
||||||
RetryTransactionRequest,
|
RetryTransactionRequest,
|
||||||
SetCoinSuspendedRequest,
|
SetCoinSuspendedRequest,
|
||||||
SetDevModeRequest,
|
|
||||||
SetWalletDeviceIdRequest,
|
SetWalletDeviceIdRequest,
|
||||||
TestPayArgs,
|
TestPayArgs,
|
||||||
TestPayResult,
|
TestPayResult,
|
||||||
@ -97,21 +95,21 @@ import {
|
|||||||
TransactionByIdRequest,
|
TransactionByIdRequest,
|
||||||
TransactionsRequest,
|
TransactionsRequest,
|
||||||
TransactionsResponse,
|
TransactionsResponse,
|
||||||
|
TxIdResponse,
|
||||||
UserAttentionByIdRequest,
|
UserAttentionByIdRequest,
|
||||||
UserAttentionsCountResponse,
|
UserAttentionsCountResponse,
|
||||||
UserAttentionsRequest,
|
UserAttentionsRequest,
|
||||||
UserAttentionsResponse,
|
UserAttentionsResponse,
|
||||||
|
ValidateIbanRequest,
|
||||||
|
ValidateIbanResponse,
|
||||||
WalletBackupContentV1,
|
WalletBackupContentV1,
|
||||||
WalletCoreVersion,
|
WalletCoreVersion,
|
||||||
WalletCurrencyInfo,
|
WalletCurrencyInfo,
|
||||||
WithdrawFakebankRequest,
|
WithdrawFakebankRequest,
|
||||||
WithdrawTestBalanceRequest,
|
WithdrawTestBalanceRequest,
|
||||||
WithdrawUriInfoResponse,
|
WithdrawUriInfoResponse,
|
||||||
ValidateIbanRequest,
|
|
||||||
ValidateIbanResponse,
|
|
||||||
TxIdResponse,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletContractData } from "./db.js";
|
import { AuditorTrustRecord, WalletContractData } from "./db.js";
|
||||||
import {
|
import {
|
||||||
AddBackupProviderRequest,
|
AddBackupProviderRequest,
|
||||||
AddBackupProviderResponse,
|
AddBackupProviderResponse,
|
||||||
@ -195,13 +193,11 @@ export enum WalletApiOperation {
|
|||||||
ConfirmPeerPullDebit = "confirmPeerPullDebit",
|
ConfirmPeerPullDebit = "confirmPeerPullDebit",
|
||||||
ClearDb = "clearDb",
|
ClearDb = "clearDb",
|
||||||
Recycle = "recycle",
|
Recycle = "recycle",
|
||||||
SetDevMode = "setDevMode",
|
|
||||||
ApplyDevExperiment = "applyDevExperiment",
|
ApplyDevExperiment = "applyDevExperiment",
|
||||||
ValidateIban = "validateIban",
|
ValidateIban = "validateIban",
|
||||||
}
|
}
|
||||||
|
|
||||||
// group: Initialization
|
// group: Initialization
|
||||||
|
|
||||||
type EmptyObject = Record<string, never>;
|
type EmptyObject = Record<string, never>;
|
||||||
/**
|
/**
|
||||||
* Initialize wallet-core.
|
* Initialize wallet-core.
|
||||||
@ -739,12 +735,6 @@ export type ApplyDevExperimentOp = {
|
|||||||
response: EmptyObject;
|
response: EmptyObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetDevModeOp = {
|
|
||||||
op: WalletApiOperation.SetDevMode;
|
|
||||||
request: SetDevModeRequest;
|
|
||||||
response: EmptyObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a simple integration test on a test deployment
|
* Run a simple integration test on a test deployment
|
||||||
* of the exchange and merchant.
|
* of the exchange and merchant.
|
||||||
@ -953,7 +943,6 @@ export type WalletOperations = {
|
|||||||
[WalletApiOperation.ClearDb]: ClearDbOp;
|
[WalletApiOperation.ClearDb]: ClearDbOp;
|
||||||
[WalletApiOperation.Recycle]: RecycleOp;
|
[WalletApiOperation.Recycle]: RecycleOp;
|
||||||
[WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp;
|
[WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp;
|
||||||
[WalletApiOperation.SetDevMode]: SetDevModeOp;
|
|
||||||
[WalletApiOperation.ValidateIban]: ValidateIbanOp;
|
[WalletApiOperation.ValidateIban]: ValidateIbanOp;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -973,3 +962,50 @@ export interface WalletCoreApiClient {
|
|||||||
payload: WalletCoreRequestType<Op>,
|
payload: WalletCoreRequestType<Op>,
|
||||||
): Promise<WalletCoreResponseType<Op>>;
|
): Promise<WalletCoreResponseType<Op>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Primitives = string | number | boolean;
|
||||||
|
|
||||||
|
export type RecursivePartial<T extends object> = {
|
||||||
|
[P in keyof T]?: T[P] extends Array<infer U extends object>
|
||||||
|
? Array<RecursivePartial<U>>
|
||||||
|
: T[P] extends Array<infer J extends Primitives>
|
||||||
|
? Array<J>
|
||||||
|
: T[P] extends object
|
||||||
|
? RecursivePartial<T[P]>
|
||||||
|
: T[P];
|
||||||
|
} & object;
|
||||||
|
|
||||||
|
export type WalletConfigParameter = RecursivePartial<WalletConfig>;
|
||||||
|
|
||||||
|
export interface WalletConfig {
|
||||||
|
/**
|
||||||
|
* Initialization values useful for a complete startup.
|
||||||
|
*
|
||||||
|
* These are values may be overridden by different wallets
|
||||||
|
*/
|
||||||
|
builtin: {
|
||||||
|
exchanges: string[];
|
||||||
|
auditors: AuditorTrustRecord[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsafe options which it should only be used to create
|
||||||
|
* testing environment.
|
||||||
|
*/
|
||||||
|
testing: {
|
||||||
|
/**
|
||||||
|
* Allow withdrawal of denominations even though they are about to expire.
|
||||||
|
*/
|
||||||
|
denomselAllowLate: boolean;
|
||||||
|
devModeActive: boolean;
|
||||||
|
insecureTrustExchange: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurations values that may be safe to show to the user
|
||||||
|
*/
|
||||||
|
features: {
|
||||||
|
batchWithdrawal: boolean;
|
||||||
|
allowHttp: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -25,12 +25,38 @@
|
|||||||
import {
|
import {
|
||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
Amounts,
|
Amounts,
|
||||||
|
CoinDumpJson,
|
||||||
|
CoinRefreshRequest,
|
||||||
|
CoinStatus,
|
||||||
|
CoreApiResponse,
|
||||||
|
DenomOperationMap,
|
||||||
|
DenominationInfo,
|
||||||
|
Duration,
|
||||||
|
ExchangeDetailedResponse,
|
||||||
|
ExchangeListItem,
|
||||||
|
ExchangeTosStatusDetails,
|
||||||
|
ExchangesListResponse,
|
||||||
|
FeeDescription,
|
||||||
|
GetExchangeTosResult,
|
||||||
|
InitResponse,
|
||||||
|
KnownBankAccounts,
|
||||||
|
KnownBankAccountsInfo,
|
||||||
|
Logger,
|
||||||
|
ManualWithdrawalDetails,
|
||||||
|
MerchantUsingTemplateDetails,
|
||||||
|
NotificationType,
|
||||||
|
RefreshReason,
|
||||||
|
TalerError,
|
||||||
|
TalerErrorCode,
|
||||||
|
URL,
|
||||||
|
ValidateIbanResponse,
|
||||||
|
WalletCoreVersion,
|
||||||
|
WalletNotification,
|
||||||
codecForAbortTransaction,
|
codecForAbortTransaction,
|
||||||
codecForAcceptBankIntegratedWithdrawalRequest,
|
codecForAcceptBankIntegratedWithdrawalRequest,
|
||||||
codecForAcceptExchangeTosRequest,
|
codecForAcceptExchangeTosRequest,
|
||||||
codecForAcceptManualWithdrawalRequet,
|
codecForAcceptManualWithdrawalRequet,
|
||||||
codecForAcceptPeerPullPaymentRequest,
|
codecForAcceptPeerPullPaymentRequest,
|
||||||
codecForConfirmPeerPushPaymentRequest,
|
|
||||||
codecForAcceptTipRequest,
|
codecForAcceptTipRequest,
|
||||||
codecForAddExchangeRequest,
|
codecForAddExchangeRequest,
|
||||||
codecForAddKnownBankAccounts,
|
codecForAddKnownBankAccounts,
|
||||||
@ -39,8 +65,9 @@ import {
|
|||||||
codecForApplyRefundFromPurchaseIdRequest,
|
codecForApplyRefundFromPurchaseIdRequest,
|
||||||
codecForApplyRefundRequest,
|
codecForApplyRefundRequest,
|
||||||
codecForCheckPeerPullPaymentRequest,
|
codecForCheckPeerPullPaymentRequest,
|
||||||
codecForPreparePeerPushCreditRequest,
|
codecForCheckPeerPushDebitRequest,
|
||||||
codecForConfirmPayRequest,
|
codecForConfirmPayRequest,
|
||||||
|
codecForConfirmPeerPushPaymentRequest,
|
||||||
codecForCreateDepositGroupRequest,
|
codecForCreateDepositGroupRequest,
|
||||||
codecForDeleteTransactionRequest,
|
codecForDeleteTransactionRequest,
|
||||||
codecForForceRefreshRequest,
|
codecForForceRefreshRequest,
|
||||||
@ -54,86 +81,58 @@ import {
|
|||||||
codecForInitiatePeerPullPaymentRequest,
|
codecForInitiatePeerPullPaymentRequest,
|
||||||
codecForInitiatePeerPushPaymentRequest,
|
codecForInitiatePeerPushPaymentRequest,
|
||||||
codecForIntegrationTestArgs,
|
codecForIntegrationTestArgs,
|
||||||
|
codecForIntegrationTestV2Args,
|
||||||
codecForListKnownBankAccounts,
|
codecForListKnownBankAccounts,
|
||||||
codecForMerchantPostOrderResponse,
|
codecForMerchantPostOrderResponse,
|
||||||
codecForPrepareDepositRequest,
|
codecForPrepareDepositRequest,
|
||||||
codecForPreparePayRequest,
|
codecForPreparePayRequest,
|
||||||
codecForPreparePayTemplateRequest,
|
codecForPreparePayTemplateRequest,
|
||||||
codecForPreparePeerPullPaymentRequest,
|
codecForPreparePeerPullPaymentRequest,
|
||||||
codecForCheckPeerPushDebitRequest,
|
codecForPreparePeerPushCreditRequest,
|
||||||
codecForPrepareRefundRequest,
|
codecForPrepareRefundRequest,
|
||||||
codecForPrepareTipRequest,
|
codecForPrepareTipRequest,
|
||||||
|
codecForResumeTransaction,
|
||||||
codecForRetryTransactionRequest,
|
codecForRetryTransactionRequest,
|
||||||
codecForSetCoinSuspendedRequest,
|
codecForSetCoinSuspendedRequest,
|
||||||
codecForSetDevModeRequest,
|
|
||||||
codecForSetWalletDeviceIdRequest,
|
codecForSetWalletDeviceIdRequest,
|
||||||
|
codecForSuspendTransaction,
|
||||||
codecForTestPayArgs,
|
codecForTestPayArgs,
|
||||||
codecForTransactionByIdRequest,
|
codecForTransactionByIdRequest,
|
||||||
codecForTransactionsRequest,
|
codecForTransactionsRequest,
|
||||||
codecForUserAttentionByIdRequest,
|
codecForUserAttentionByIdRequest,
|
||||||
codecForUserAttentionsRequest,
|
codecForUserAttentionsRequest,
|
||||||
|
codecForValidateIbanRequest,
|
||||||
codecForWithdrawFakebankRequest,
|
codecForWithdrawFakebankRequest,
|
||||||
codecForWithdrawTestBalance,
|
codecForWithdrawTestBalance,
|
||||||
CoinDumpJson,
|
|
||||||
CoinRefreshRequest,
|
|
||||||
CoinStatus,
|
|
||||||
constructPayUri,
|
constructPayUri,
|
||||||
CoreApiResponse,
|
|
||||||
DenominationInfo,
|
|
||||||
DenomOperationMap,
|
|
||||||
Duration,
|
|
||||||
durationFromSpec,
|
durationFromSpec,
|
||||||
durationMin,
|
durationMin,
|
||||||
ExchangeDetailedResponse,
|
getErrorDetailFromException,
|
||||||
ExchangeListItem,
|
|
||||||
ExchangesListResponse,
|
|
||||||
ExchangeTosStatusDetails,
|
|
||||||
FeeDescription,
|
|
||||||
GetExchangeTosResult,
|
|
||||||
InitResponse,
|
|
||||||
j2s,
|
j2s,
|
||||||
KnownBankAccounts,
|
|
||||||
KnownBankAccountsInfo,
|
|
||||||
Logger,
|
|
||||||
ManualWithdrawalDetails,
|
|
||||||
MerchantUsingTemplateDetails,
|
|
||||||
NotificationType,
|
|
||||||
parsePayTemplateUri,
|
parsePayTemplateUri,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
RefreshReason,
|
|
||||||
TalerErrorCode,
|
|
||||||
URL,
|
|
||||||
WalletCoreVersion,
|
|
||||||
WalletNotification,
|
|
||||||
codecForSuspendTransaction,
|
|
||||||
codecForResumeTransaction,
|
|
||||||
validateIban,
|
validateIban,
|
||||||
codecForValidateIbanRequest,
|
|
||||||
ValidateIbanResponse,
|
|
||||||
codecForIntegrationTestV2Args,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import {
|
||||||
|
HttpRequestLibrary,
|
||||||
|
readSuccessResponseJsonOrThrow,
|
||||||
|
} from "@gnu-taler/taler-util/http";
|
||||||
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
|
||||||
import {
|
import {
|
||||||
CryptoDispatcher,
|
CryptoDispatcher,
|
||||||
CryptoWorkerFactory,
|
CryptoWorkerFactory,
|
||||||
} from "./crypto/workers/crypto-dispatcher.js";
|
} from "./crypto/workers/crypto-dispatcher.js";
|
||||||
import {
|
import {
|
||||||
AuditorTrustRecord,
|
|
||||||
clearDatabase,
|
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
ConfigRecordKey,
|
ConfigRecordKey,
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
ExchangeDetailsRecord,
|
ExchangeDetailsRecord,
|
||||||
|
WalletStoresV1,
|
||||||
|
clearDatabase,
|
||||||
exportDb,
|
exportDb,
|
||||||
importDb,
|
importDb,
|
||||||
WalletStoresV1,
|
|
||||||
} from "./db.js";
|
} from "./db.js";
|
||||||
import {
|
import { DevExperimentHttpLib, applyDevExperiment } from "./dev-experiments.js";
|
||||||
applyDevExperiment,
|
|
||||||
maybeInitDevMode,
|
|
||||||
setDevMode,
|
|
||||||
} from "./dev-experiments.js";
|
|
||||||
import { getErrorDetailFromException, TalerError } from "@gnu-taler/taler-util";
|
|
||||||
import {
|
import {
|
||||||
ActiveLongpollInfo,
|
ActiveLongpollInfo,
|
||||||
ExchangeOperations,
|
ExchangeOperations,
|
||||||
@ -198,18 +197,18 @@ import {
|
|||||||
processPurchase,
|
processPurchase,
|
||||||
} from "./operations/pay-merchant.js";
|
} from "./operations/pay-merchant.js";
|
||||||
import {
|
import {
|
||||||
confirmPeerPullDebit,
|
|
||||||
confirmPeerPushCredit,
|
|
||||||
preparePeerPullDebit,
|
|
||||||
preparePeerPushCredit,
|
|
||||||
initiatePeerPullPayment,
|
|
||||||
initiatePeerPushPayment,
|
|
||||||
checkPeerPullPaymentInitiation,
|
checkPeerPullPaymentInitiation,
|
||||||
checkPeerPushDebit,
|
checkPeerPushDebit,
|
||||||
|
confirmPeerPullDebit,
|
||||||
|
confirmPeerPushCredit,
|
||||||
|
initiatePeerPullPayment,
|
||||||
|
initiatePeerPushPayment,
|
||||||
|
preparePeerPullDebit,
|
||||||
|
preparePeerPushCredit,
|
||||||
processPeerPullCredit,
|
processPeerPullCredit,
|
||||||
processPeerPushInitiation,
|
|
||||||
processPeerPullDebit,
|
processPeerPullDebit,
|
||||||
processPeerPushCredit,
|
processPeerPushCredit,
|
||||||
|
processPeerPushInitiation,
|
||||||
} from "./operations/pay-peer.js";
|
} from "./operations/pay-peer.js";
|
||||||
import { getPendingOperations } from "./operations/pending.js";
|
import { getPendingOperations } from "./operations/pending.js";
|
||||||
import {
|
import {
|
||||||
@ -252,10 +251,6 @@ import {
|
|||||||
selectBestForOverlappingDenominations,
|
selectBestForOverlappingDenominations,
|
||||||
selectMinimumFee,
|
selectMinimumFee,
|
||||||
} from "./util/denominations.js";
|
} from "./util/denominations.js";
|
||||||
import {
|
|
||||||
HttpRequestLibrary,
|
|
||||||
readSuccessResponseJsonOrThrow,
|
|
||||||
} from "@gnu-taler/taler-util/http";
|
|
||||||
import { checkDbInvariant } from "./util/invariants.js";
|
import { checkDbInvariant } from "./util/invariants.js";
|
||||||
import {
|
import {
|
||||||
AsyncCondition,
|
AsyncCondition,
|
||||||
@ -275,22 +270,14 @@ import {
|
|||||||
WALLET_MERCHANT_PROTOCOL_VERSION,
|
WALLET_MERCHANT_PROTOCOL_VERSION,
|
||||||
} from "./versions.js";
|
} from "./versions.js";
|
||||||
import {
|
import {
|
||||||
|
RecursivePartial,
|
||||||
WalletApiOperation,
|
WalletApiOperation,
|
||||||
|
WalletConfig,
|
||||||
|
WalletConfigParameter,
|
||||||
WalletCoreApiClient,
|
WalletCoreApiClient,
|
||||||
WalletCoreResponseType,
|
WalletCoreResponseType,
|
||||||
} from "./wallet-api-types.js";
|
} from "./wallet-api-types.js";
|
||||||
|
|
||||||
const builtinAuditors: AuditorTrustRecord[] = [
|
|
||||||
{
|
|
||||||
currency: "KUDOS",
|
|
||||||
auditorPub: "BW9DC48PHQY4NH011SHHX36DZZ3Q22Y6X7FZ1VD1CMZ2PTFZ6PN0",
|
|
||||||
auditorBaseUrl: "https://auditor.demo.taler.net/",
|
|
||||||
uids: ["5P25XF8TVQP9AW6VYGY2KV47WT5Y3ZXFSJAA570GJPX5SVJXKBVG"],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const builtinExchanges: string[] = ["https://exchange.demo.taler.net/"];
|
|
||||||
|
|
||||||
const logger = new Logger("wallet.ts");
|
const logger = new Logger("wallet.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -495,10 +482,10 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.info("importing default exchanges and auditors");
|
logger.info("importing default exchanges and auditors");
|
||||||
for (const c of builtinAuditors) {
|
for (const c of ws.config.builtin.auditors) {
|
||||||
await tx.auditorTrust.put(c);
|
await tx.auditorTrust.put(c);
|
||||||
}
|
}
|
||||||
for (const baseUrl of builtinExchanges) {
|
for (const baseUrl of ws.config.builtin.exchanges) {
|
||||||
const now = AbsoluteTime.now();
|
const now = AbsoluteTime.now();
|
||||||
provideExchangeRecordInTx(ws, tx, baseUrl, now);
|
provideExchangeRecordInTx(ws, tx, baseUrl, now);
|
||||||
}
|
}
|
||||||
@ -1018,7 +1005,6 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
|
|||||||
logger.trace("filling defaults");
|
logger.trace("filling defaults");
|
||||||
await fillDefaults(ws);
|
await fillDefaults(ws);
|
||||||
}
|
}
|
||||||
await maybeInitDevMode(ws);
|
|
||||||
const resp: InitResponse = {
|
const resp: InitResponse = {
|
||||||
versionInfo: getVersion(ws),
|
versionInfo: getVersion(ws),
|
||||||
};
|
};
|
||||||
@ -1482,11 +1468,6 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
|
|||||||
await applyDevExperiment(ws, req.devExperimentUri);
|
await applyDevExperiment(ws, req.devExperimentUri);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
case WalletApiOperation.SetDevMode: {
|
|
||||||
const req = codecForSetDevModeRequest().decode(payload);
|
|
||||||
await setDevMode(ws, req.devModeEnabled);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
case WalletApiOperation.GetVersion: {
|
case WalletApiOperation.GetVersion: {
|
||||||
return getVersion(ws);
|
return getVersion(ws);
|
||||||
}
|
}
|
||||||
@ -1509,7 +1490,7 @@ export function getVersion(ws: InternalWalletState): WalletCoreVersion {
|
|||||||
exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
|
exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
|
merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
|
||||||
bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
|
bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
|
||||||
devMode: ws.devModeActive,
|
devMode: false,
|
||||||
};
|
};
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
@ -1575,8 +1556,15 @@ export class Wallet {
|
|||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
timer: TimerAPI,
|
timer: TimerAPI,
|
||||||
cryptoWorkerFactory: CryptoWorkerFactory,
|
cryptoWorkerFactory: CryptoWorkerFactory,
|
||||||
|
config?: WalletConfigParameter,
|
||||||
) {
|
) {
|
||||||
this.ws = new InternalWalletStateImpl(db, http, timer, cryptoWorkerFactory);
|
this.ws = new InternalWalletStateImpl(
|
||||||
|
db,
|
||||||
|
http,
|
||||||
|
timer,
|
||||||
|
cryptoWorkerFactory,
|
||||||
|
config ?? {},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get client(): WalletCoreApiClient {
|
get client(): WalletCoreApiClient {
|
||||||
@ -1586,29 +1574,22 @@ export class Wallet {
|
|||||||
return this._client;
|
return this._client;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Trust the exchange, do not validate signatures.
|
|
||||||
* Only used to benchmark the exchange.
|
|
||||||
*/
|
|
||||||
setInsecureTrustExchange(): void {
|
|
||||||
this.ws.insecureTrustExchange = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBatchWithdrawal(enable: boolean): void {
|
|
||||||
this.ws.batchWithdrawal = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(
|
static async create(
|
||||||
db: DbAccess<typeof WalletStoresV1>,
|
db: DbAccess<typeof WalletStoresV1>,
|
||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
timer: TimerAPI,
|
timer: TimerAPI,
|
||||||
cryptoWorkerFactory: CryptoWorkerFactory,
|
cryptoWorkerFactory: CryptoWorkerFactory,
|
||||||
|
config?: WalletConfigParameter,
|
||||||
): Promise<Wallet> {
|
): Promise<Wallet> {
|
||||||
const w = new Wallet(db, http, timer, cryptoWorkerFactory);
|
const w = new Wallet(db, http, timer, cryptoWorkerFactory, config);
|
||||||
w._client = await getClientFromWalletState(w.ws);
|
w._client = await getClientFromWalletState(w.ws);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getDefaultConfig(): Readonly<WalletConfig> {
|
||||||
|
return InternalWalletStateImpl.defaultConfig;
|
||||||
|
}
|
||||||
|
|
||||||
addNotificationListener(f: (n: WalletNotification) => void): void {
|
addNotificationListener(f: (n: WalletNotification) => void): void {
|
||||||
return this.ws.addNotificationListener(f);
|
return this.ws.addNotificationListener(f);
|
||||||
}
|
}
|
||||||
@ -1650,10 +1631,6 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
|
|
||||||
merchantInfoCache: Record<string, MerchantInfo> = {};
|
merchantInfoCache: Record<string, MerchantInfo> = {};
|
||||||
|
|
||||||
insecureTrustExchange = false;
|
|
||||||
|
|
||||||
batchWithdrawal = false;
|
|
||||||
|
|
||||||
readonly timerGroup: TimerGroup;
|
readonly timerGroup: TimerGroup;
|
||||||
latch = new AsyncCondition();
|
latch = new AsyncCondition();
|
||||||
stopped = false;
|
stopped = false;
|
||||||
@ -1662,8 +1639,6 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
|
|
||||||
initCalled = false;
|
initCalled = false;
|
||||||
|
|
||||||
devModeActive = false;
|
|
||||||
|
|
||||||
exchangeOps: ExchangeOperations = {
|
exchangeOps: ExchangeOperations = {
|
||||||
getExchangeDetails,
|
getExchangeDetails,
|
||||||
getExchangeTrust,
|
getExchangeTrust,
|
||||||
@ -1696,6 +1671,31 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
*/
|
*/
|
||||||
private resourceLocks: Set<string> = new Set();
|
private resourceLocks: Set<string> = new Set();
|
||||||
|
|
||||||
|
config: Readonly<WalletConfig>;
|
||||||
|
|
||||||
|
public static defaultConfig: Readonly<WalletConfig> = {
|
||||||
|
builtin: {
|
||||||
|
exchanges: ["https://exchange.demo.taler.net/"],
|
||||||
|
auditors: [
|
||||||
|
{
|
||||||
|
currency: "KUDOS",
|
||||||
|
auditorPub: "BW9DC48PHQY4NH011SHHX36DZZ3Q22Y6X7FZ1VD1CMZ2PTFZ6PN0",
|
||||||
|
auditorBaseUrl: "https://auditor.demo.taler.net/",
|
||||||
|
uids: ["5P25XF8TVQP9AW6VYGY2KV47WT5Y3ZXFSJAA570GJPX5SVJXKBVG"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
features: {
|
||||||
|
batchWithdrawal: false,
|
||||||
|
allowHttp: false,
|
||||||
|
},
|
||||||
|
testing: {
|
||||||
|
devModeActive: false,
|
||||||
|
insecureTrustExchange: false,
|
||||||
|
denomselAllowLate: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// FIXME: Make this a getter and make
|
// FIXME: Make this a getter and make
|
||||||
// the actual value nullable.
|
// the actual value nullable.
|
||||||
@ -1705,10 +1705,15 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
public http: HttpRequestLibrary,
|
public http: HttpRequestLibrary,
|
||||||
public timer: TimerAPI,
|
public timer: TimerAPI,
|
||||||
cryptoWorkerFactory: CryptoWorkerFactory,
|
cryptoWorkerFactory: CryptoWorkerFactory,
|
||||||
|
config: WalletConfigParameter,
|
||||||
) {
|
) {
|
||||||
this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory);
|
this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory);
|
||||||
this.cryptoApi = this.cryptoDispatcher.cryptoApi;
|
this.cryptoApi = this.cryptoDispatcher.cryptoApi;
|
||||||
this.timerGroup = new TimerGroup(timer);
|
this.timerGroup = new TimerGroup(timer);
|
||||||
|
this.config = deepMerge(InternalWalletStateImpl.defaultConfig, config);
|
||||||
|
if (this.config.testing.devModeActive) {
|
||||||
|
this.http = new DevExperimentHttpLib(this.http);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDenomInfo(
|
async getDenomInfo(
|
||||||
@ -1808,3 +1813,29 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take the full object as template, create a new result with all the values.
|
||||||
|
* Use the override object to change the values in the result
|
||||||
|
* return result
|
||||||
|
* @param full
|
||||||
|
* @param override
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function deepMerge<T extends object>(
|
||||||
|
full: T,
|
||||||
|
override: RecursivePartial<T>,
|
||||||
|
): T {
|
||||||
|
const keys = Object.keys(full);
|
||||||
|
const result = { ...full };
|
||||||
|
for (const k of keys) {
|
||||||
|
// @ts-ignore
|
||||||
|
const newVal = override[k];
|
||||||
|
if (newVal === undefined) continue;
|
||||||
|
// @ts-ignore
|
||||||
|
result[k] =
|
||||||
|
// @ts-ignore
|
||||||
|
typeof newVal === "object" ? deepMerge(full[k], newVal) : newVal;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { JustInDevMode } from "./components/JustInDevMode.js";
|
import { EnabledBySettings } from "./components/EnabledBySettings.js";
|
||||||
import {
|
import {
|
||||||
NavigationHeader,
|
NavigationHeader,
|
||||||
NavigationHeaderHolder,
|
NavigationHeaderHolder,
|
||||||
@ -183,11 +183,11 @@ export function PopupNavBar({ path }: { path?: PopupNavBarOptions }): VNode {
|
|||||||
<a href={Pages.balance} class={path === "balance" ? "active" : ""}>
|
<a href={Pages.balance} class={path === "balance" ? "active" : ""}>
|
||||||
<i18n.Translate>Balance</i18n.Translate>
|
<i18n.Translate>Balance</i18n.Translate>
|
||||||
</a>
|
</a>
|
||||||
<JustInDevMode>
|
<EnabledBySettings name="backup">
|
||||||
<a href={Pages.backup} class={path === "backup" ? "active" : ""}>
|
<a href={Pages.backup} class={path === "backup" ? "active" : ""}>
|
||||||
<i18n.Translate>Backup</i18n.Translate>
|
<i18n.Translate>Backup</i18n.Translate>
|
||||||
</a>
|
</a>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
<div style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}>
|
<div style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}>
|
||||||
{attentionCount > 0 ? (
|
{attentionCount > 0 ? (
|
||||||
<a href={Pages.notifications}>
|
<a href={Pages.notifications}>
|
||||||
@ -238,11 +238,11 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode {
|
|||||||
<a href={Pages.balance} class={path === "balance" ? "active" : ""}>
|
<a href={Pages.balance} class={path === "balance" ? "active" : ""}>
|
||||||
<i18n.Translate>Balance</i18n.Translate>
|
<i18n.Translate>Balance</i18n.Translate>
|
||||||
</a>
|
</a>
|
||||||
<JustInDevMode>
|
<EnabledBySettings name="backup">
|
||||||
<a href={Pages.backup} class={path === "backup" ? "active" : ""}>
|
<a href={Pages.backup} class={path === "backup" ? "active" : ""}>
|
||||||
<i18n.Translate>Backup</i18n.Translate>
|
<i18n.Translate>Backup</i18n.Translate>
|
||||||
</a>
|
</a>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
|
|
||||||
{attentionCount > 0 ? (
|
{attentionCount > 0 ? (
|
||||||
<a href={Pages.notifications}>
|
<a href={Pages.notifications}>
|
||||||
@ -252,11 +252,11 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode {
|
|||||||
<Fragment />
|
<Fragment />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<JustInDevMode>
|
<EnabledBySettings name="advanceMode">
|
||||||
<a href={Pages.dev} class={path === "dev" ? "active" : ""}>
|
<a href={Pages.dev} class={path === "dev" ? "active" : ""}>
|
||||||
<i18n.Translate>Dev</i18n.Translate>
|
<i18n.Translate>Dev tools</i18n.Translate>
|
||||||
</a>
|
</a>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}
|
style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}
|
||||||
|
@ -27,7 +27,6 @@ import { platform, setupPlatform } from "./platform/background.js";
|
|||||||
import devAPI from "./platform/dev.js";
|
import devAPI from "./platform/dev.js";
|
||||||
import { wxMain } from "./wxBackend.js";
|
import { wxMain } from "./wxBackend.js";
|
||||||
|
|
||||||
console.log("Wallet setup for Dev API");
|
|
||||||
setupPlatform(devAPI);
|
setupPlatform(devAPI);
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
|
@ -35,10 +35,8 @@ const isFirefox =
|
|||||||
// FIXME: create different entry point for any platform instead of
|
// FIXME: create different entry point for any platform instead of
|
||||||
// switching in runtime
|
// switching in runtime
|
||||||
if (isFirefox) {
|
if (isFirefox) {
|
||||||
console.log("Wallet setup for Firefox API");
|
|
||||||
setupPlatform(firefoxAPI);
|
setupPlatform(firefoxAPI);
|
||||||
} else {
|
} else {
|
||||||
console.log("Wallet setup for Chrome API");
|
|
||||||
setupPlatform(chromeAPI);
|
setupPlatform(chromeAPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,25 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||||
import { useDevContext } from "../context/devContext.js";
|
import { useSettings } from "../hooks/useSettings.js";
|
||||||
|
import { Settings } from "../platform/api.js";
|
||||||
|
|
||||||
export function JustInDevMode({
|
export function EnabledBySettings<K extends keyof Settings>({
|
||||||
children,
|
children,
|
||||||
|
value,
|
||||||
|
name,
|
||||||
}: {
|
}: {
|
||||||
|
name: K;
|
||||||
|
value?: Settings[K];
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
}): VNode {
|
}): VNode {
|
||||||
const { devMode } = useDevContext();
|
const [settings] = useSettings();
|
||||||
if (!devMode) return <Fragment />;
|
if (value === undefined) {
|
||||||
|
if (!settings[name]) return <Fragment />;
|
||||||
|
return <Fragment>{children}</Fragment>;
|
||||||
|
}
|
||||||
|
if (settings[name] !== value) {
|
||||||
|
return <Fragment />;
|
||||||
|
}
|
||||||
return <Fragment>{children}</Fragment>;
|
return <Fragment>{children}</Fragment>;
|
||||||
}
|
}
|
@ -17,8 +17,8 @@ import { TalerErrorDetail, TranslatedString } from "@gnu-taler/taler-util";
|
|||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import arrowDown from "../svg/chevron-down.svg";
|
import arrowDown from "../svg/chevron-down.svg";
|
||||||
import { useDevContext } from "../context/devContext.js";
|
|
||||||
import { ErrorBox } from "./styled/index.js";
|
import { ErrorBox } from "./styled/index.js";
|
||||||
|
import { EnabledBySettings } from "./EnabledBySettings.js";
|
||||||
|
|
||||||
export function ErrorTalerOperation({
|
export function ErrorTalerOperation({
|
||||||
title,
|
title,
|
||||||
@ -27,7 +27,6 @@ export function ErrorTalerOperation({
|
|||||||
title?: TranslatedString;
|
title?: TranslatedString;
|
||||||
error?: TalerErrorDetail;
|
error?: TalerErrorDetail;
|
||||||
}): VNode | null {
|
}): VNode | null {
|
||||||
const { devMode } = useDevContext();
|
|
||||||
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
||||||
|
|
||||||
if (!title || !error) return null;
|
if (!title || !error) return null;
|
||||||
@ -62,11 +61,11 @@ export function ErrorTalerOperation({
|
|||||||
<b>{error.hint}</b> {!errorHint ? "" : `: ${errorHint}`}{" "}
|
<b>{error.hint}</b> {!errorHint ? "" : `: ${errorHint}`}{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{devMode && (
|
<EnabledBySettings name="showJsonOnError">
|
||||||
<div style={{ textAlign: "left", overflowX: "auto" }}>
|
<div style={{ textAlign: "left", overflowX: "auto" }}>
|
||||||
<pre>{JSON.stringify(error, undefined, 2)}</pre>
|
<pre>{JSON.stringify(error, undefined, 2)}</pre>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</EnabledBySettings>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</ErrorBox>
|
</ErrorBox>
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ExchangeTosStatus, GetExchangeTosResult } from "@gnu-taler/taler-util";
|
import {
|
||||||
|
ExchangeTosStatus,
|
||||||
|
GetExchangeTosResult,
|
||||||
|
Logger,
|
||||||
|
} from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
export function buildTermsOfServiceState(
|
export function buildTermsOfServiceState(
|
||||||
tos: GetExchangeTosResult,
|
tos: GetExchangeTosResult,
|
||||||
@ -27,6 +31,8 @@ export function buildTermsOfServiceState(
|
|||||||
return { content, status: tos.tosStatus, version: tos.currentEtag };
|
return { content, status: tos.tosStatus, version: tos.currentEtag };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logger = new Logger("termsofservice");
|
||||||
|
|
||||||
function parseTermsOfServiceContent(
|
function parseTermsOfServiceContent(
|
||||||
type: string,
|
type: string,
|
||||||
text: string,
|
text: string,
|
||||||
@ -36,28 +42,28 @@ function parseTermsOfServiceContent(
|
|||||||
const document = new DOMParser().parseFromString(text, "text/xml");
|
const document = new DOMParser().parseFromString(text, "text/xml");
|
||||||
return { type: "xml", document };
|
return { type: "xml", document };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
logger.error("error parsing xml", e);
|
||||||
}
|
}
|
||||||
} else if (type === "text/html") {
|
} else if (type === "text/html") {
|
||||||
try {
|
try {
|
||||||
const href = new URL(text);
|
const href = new URL(text);
|
||||||
return { type: "html", href };
|
return { type: "html", href };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
logger.error("error parsing url", e);
|
||||||
}
|
}
|
||||||
} else if (type === "text/json") {
|
} else if (type === "text/json") {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text);
|
const data = JSON.parse(text);
|
||||||
return { type: "json", data };
|
return { type: "json", data };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
logger.error("error parsing json", e);
|
||||||
}
|
}
|
||||||
} else if (type === "text/pdf") {
|
} else if (type === "text/pdf") {
|
||||||
try {
|
try {
|
||||||
const location = new URL(text);
|
const location = new URL(text);
|
||||||
return { type: "pdf", location };
|
return { type: "pdf", location };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
logger.error("error parsing url", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const content = text;
|
const content = text;
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2022 Taler Systems S.A.
|
|
||||||
|
|
||||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { createContext, h, VNode } from "preact";
|
|
||||||
import { useContext } from "preact/hooks";
|
|
||||||
import { useWalletDevMode } from "../hooks/useWalletDevMode.js";
|
|
||||||
|
|
||||||
interface Type {
|
|
||||||
devMode: boolean;
|
|
||||||
toggle: () => Promise<void>;
|
|
||||||
}
|
|
||||||
const Context = createContext<Type>({
|
|
||||||
devMode: false,
|
|
||||||
toggle: async () => {
|
|
||||||
null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useDevContext = (): Type => useContext(Context);
|
|
||||||
|
|
||||||
export const DevContextProviderForTesting = ({
|
|
||||||
value,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
value?: boolean;
|
|
||||||
children: any;
|
|
||||||
}): VNode => {
|
|
||||||
return h(Context.Provider, {
|
|
||||||
value: {
|
|
||||||
devMode: !!value,
|
|
||||||
toggle: async () => {
|
|
||||||
null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DevContextProvider = ({ children }: { children: any }): VNode => {
|
|
||||||
const devModeToggle = useWalletDevMode();
|
|
||||||
const value: Type = {
|
|
||||||
devMode: !!devModeToggle.value,
|
|
||||||
toggle: devModeToggle.toggle,
|
|
||||||
};
|
|
||||||
//support for function as children, useful for getting the value right away
|
|
||||||
children =
|
|
||||||
children.length === 1 && typeof children === "function"
|
|
||||||
? children(value)
|
|
||||||
: children;
|
|
||||||
|
|
||||||
return h(Context.Provider, { value, children });
|
|
||||||
};
|
|
@ -167,8 +167,6 @@ export function useComponentState({
|
|||||||
if (fu) {
|
if (fu) {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
document.location.href = fu;
|
document.location.href = fu;
|
||||||
} else {
|
|
||||||
console.log(`should d to ${fu}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSuccess(res.transactionId);
|
onSuccess(res.transactionId);
|
||||||
|
@ -30,7 +30,6 @@ export function ReadyView({
|
|||||||
}: State.FillTemplate): VNode {
|
}: State.FillTemplate): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
|
|
||||||
console.log("is summary", !!summary);
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section style={{ textAlign: "left" }}>
|
<section style={{ textAlign: "left" }}>
|
||||||
|
@ -51,7 +51,6 @@ export function useClipboardPermissions(): ToggleHandler {
|
|||||||
// .call("toggleHeaderListener", false)
|
// .call("toggleHeaderListener", false)
|
||||||
// .then((r) => setEnabled(r.newValue));
|
// .then((r) => setEnabled(r.newValue));
|
||||||
// } catch (e) {
|
// } catch (e) {
|
||||||
// console.log(e);
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -36,7 +36,6 @@ export function useSettings(): [
|
|||||||
function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
|
function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
|
||||||
const newValue = { ...parsed, [k]: v };
|
const newValue = { ...parsed, [k]: v };
|
||||||
const json = JSON.stringify(newValue);
|
const json = JSON.stringify(newValue);
|
||||||
console.log(json);
|
|
||||||
update(json);
|
update(json);
|
||||||
}
|
}
|
||||||
return [parsed, updateField];
|
return [parsed, updateField];
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2022 Taler Systems S.A.
|
|
||||||
|
|
||||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
|
||||||
import { useEffect, useState } from "preact/hooks";
|
|
||||||
import { useBackendContext } from "../context/backend.js";
|
|
||||||
|
|
||||||
type Result = {
|
|
||||||
value: boolean | undefined;
|
|
||||||
toggle: () => Promise<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useWalletDevMode(): Result {
|
|
||||||
const [enabled, setEnabled] = useState<undefined | boolean>(undefined);
|
|
||||||
const api = useBackendContext();
|
|
||||||
// const { pushAlertOnError } = useAlertContext();
|
|
||||||
|
|
||||||
async function handleOpen(): Promise<void> {
|
|
||||||
const nextValue = !enabled;
|
|
||||||
await api.wallet.call(WalletApiOperation.SetDevMode, {
|
|
||||||
devModeEnabled: nextValue,
|
|
||||||
});
|
|
||||||
setEnabled(nextValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function getValue(): Promise<void> {
|
|
||||||
const res = await api.wallet.call(WalletApiOperation.GetVersion, {});
|
|
||||||
setEnabled(res.devMode);
|
|
||||||
}
|
|
||||||
getValue();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
|
||||||
value: enabled,
|
|
||||||
toggle: handleOpen,
|
|
||||||
};
|
|
||||||
}
|
|
@ -15,7 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CoreApiResponse, NotificationType } from "@gnu-taler/taler-util";
|
import { CoreApiResponse, NotificationType } from "@gnu-taler/taler-util";
|
||||||
import { WalletOperations } from "@gnu-taler/taler-wallet-core";
|
import {
|
||||||
|
WalletConfig,
|
||||||
|
WalletConfigParameter,
|
||||||
|
WalletOperations,
|
||||||
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { BackgroundOperations } from "../wxApi.js";
|
import { BackgroundOperations } from "../wxApi.js";
|
||||||
import {
|
import {
|
||||||
ExtensionOperations,
|
ExtensionOperations,
|
||||||
@ -87,12 +91,35 @@ export interface WalletWebExVersion {
|
|||||||
version: string;
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Settings {
|
type F = WalletConfig["features"];
|
||||||
|
type kf = keyof F;
|
||||||
|
type WebexWalletConfig = {
|
||||||
|
[P in keyof F as `wallet${Capitalize<P>}`]: F[P];
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Settings extends WebexWalletConfig {
|
||||||
injectTalerSupport: boolean;
|
injectTalerSupport: boolean;
|
||||||
|
advanceMode: boolean;
|
||||||
|
backup: boolean;
|
||||||
|
langSelector: boolean;
|
||||||
|
showJsonOnError: boolean;
|
||||||
|
extendedAccountTypes: boolean;
|
||||||
|
//WORKAROUND
|
||||||
|
//Able to delete tx in dev mode
|
||||||
|
//FIXME: remove this when DD37 is implemented
|
||||||
|
deleteActiveTransactions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultSettings: Settings = {
|
export const defaultSettings: Settings = {
|
||||||
injectTalerSupport: false,
|
injectTalerSupport: false,
|
||||||
|
advanceMode: false,
|
||||||
|
backup: false,
|
||||||
|
langSelector: false,
|
||||||
|
deleteActiveTransactions: false,
|
||||||
|
showJsonOnError: false,
|
||||||
|
extendedAccountTypes: false,
|
||||||
|
walletAllowHttp: false,
|
||||||
|
walletBatchWithdrawal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +45,7 @@ function isFirefox(): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addPermissionsListener(callback: (p: Permissions) => void): void {
|
function addPermissionsListener(callback: (p: Permissions) => void): void {
|
||||||
console.log("addPermissionListener is not supported for Firefox");
|
throw Error("addPermissionListener is not supported for Firefox");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPermissionsApi(): CrossBrowserPermissionsApi {
|
function getPermissionsApi(): CrossBrowserPermissionsApi {
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
* @author sebasjm
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
TranslationProvider,
|
||||||
|
useTranslationContext,
|
||||||
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||||
import { route, Route, Router } from "preact-router";
|
import { route, Route, Router } from "preact-router";
|
||||||
@ -27,29 +31,22 @@ import { useEffect, useState } from "preact/hooks";
|
|||||||
import PendingTransactions from "../components/PendingTransactions.js";
|
import PendingTransactions from "../components/PendingTransactions.js";
|
||||||
import { PopupBox } from "../components/styled/index.js";
|
import { PopupBox } from "../components/styled/index.js";
|
||||||
import { AlertProvider } from "../context/alert.js";
|
import { AlertProvider } from "../context/alert.js";
|
||||||
import { DevContextProvider } from "../context/devContext.js";
|
|
||||||
import { IoCProviderForRuntime } from "../context/iocContext.js";
|
import { IoCProviderForRuntime } from "../context/iocContext.js";
|
||||||
import {
|
|
||||||
TranslationProvider,
|
|
||||||
useTranslationContext,
|
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
|
||||||
import { useTalerActionURL } from "../hooks/useTalerActionURL.js";
|
import { useTalerActionURL } from "../hooks/useTalerActionURL.js";
|
||||||
|
import { strings } from "../i18n/strings.js";
|
||||||
import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
|
import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
|
||||||
import { platform } from "../platform/foreground.js";
|
import { platform } from "../platform/foreground.js";
|
||||||
import { BackupPage } from "../wallet/BackupPage.js";
|
import { BackupPage } from "../wallet/BackupPage.js";
|
||||||
import { ProviderDetailPage } from "../wallet/ProviderDetailPage.js";
|
import { ProviderDetailPage } from "../wallet/ProviderDetailPage.js";
|
||||||
import { BalancePage } from "./BalancePage.js";
|
import { BalancePage } from "./BalancePage.js";
|
||||||
import { TalerActionFound } from "./TalerActionFound.js";
|
import { TalerActionFound } from "./TalerActionFound.js";
|
||||||
import { strings } from "../i18n/strings.js";
|
|
||||||
|
|
||||||
export function Application(): VNode {
|
export function Application(): VNode {
|
||||||
return (
|
return (
|
||||||
<TranslationProvider source={strings}>
|
<TranslationProvider source={strings}>
|
||||||
<DevContextProvider>
|
|
||||||
<IoCProviderForRuntime>
|
<IoCProviderForRuntime>
|
||||||
<ApplicationView />
|
<ApplicationView />
|
||||||
</IoCProviderForRuntime>
|
</IoCProviderForRuntime>
|
||||||
</DevContextProvider>
|
|
||||||
</TranslationProvider>
|
</TranslationProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import { setupPlatform } from "./platform/foreground.js";
|
|||||||
import devAPI from "./platform/dev.js";
|
import devAPI from "./platform/dev.js";
|
||||||
import { Application } from "./popup/Application.js";
|
import { Application } from "./popup/Application.js";
|
||||||
|
|
||||||
console.log("Wallet setup for Dev API");
|
|
||||||
setupPlatform(devAPI);
|
setupPlatform(devAPI);
|
||||||
|
|
||||||
function main(): void {
|
function main(): void {
|
||||||
|
@ -32,10 +32,8 @@ import { Application } from "./popup/Application.js";
|
|||||||
//switching in runtime
|
//switching in runtime
|
||||||
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
|
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
|
||||||
if (isFirefox) {
|
if (isFirefox) {
|
||||||
console.log("Wallet setup for Firefox API");
|
|
||||||
setupPlatform(firefoxAPI);
|
setupPlatform(firefoxAPI);
|
||||||
} else {
|
} else {
|
||||||
console.log("Wallet setup for Chrome API");
|
|
||||||
setupPlatform(chromeAPI);
|
setupPlatform(chromeAPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ import { strings } from "./i18n/strings.js";
|
|||||||
// When doing tests we want the requestAnimationFrame to be as fast as possible.
|
// When doing tests we want the requestAnimationFrame to be as fast as possible.
|
||||||
// without this option the RAF will timeout after 100ms making the tests slower
|
// without this option the RAF will timeout after 100ms making the tests slower
|
||||||
options.requestAnimationFrame = (fn: () => void) => {
|
options.requestAnimationFrame = (fn: () => void) => {
|
||||||
// console.log("RAF called")
|
|
||||||
return fn();
|
return fn();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,15 +20,21 @@
|
|||||||
* @author sebasjm
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { TranslatedString } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
TalerUriAction,
|
TranslationProvider,
|
||||||
TranslatedString,
|
useTranslationContext,
|
||||||
parseTalerUri,
|
} from "@gnu-taler/web-util/lib/index.browser";
|
||||||
} from "@gnu-taler/taler-util";
|
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
import { ComponentChildren, Fragment, VNode, h } from "preact";
|
||||||
import { route, Route, Router } from "preact-router";
|
import { Route, Router, route } from "preact-router";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
|
import {
|
||||||
|
Pages,
|
||||||
|
WalletNavBar,
|
||||||
|
WalletNavBarOptions,
|
||||||
|
getPathnameForTalerURI,
|
||||||
|
} from "../NavigationBar.js";
|
||||||
import { AlertView, CurrentAlerts } from "../components/CurrentAlerts.js";
|
import { AlertView, CurrentAlerts } from "../components/CurrentAlerts.js";
|
||||||
import { LogoHeader } from "../components/LogoHeader.js";
|
import { LogoHeader } from "../components/LogoHeader.js";
|
||||||
import PendingTransactions from "../components/PendingTransactions.js";
|
import PendingTransactions from "../components/PendingTransactions.js";
|
||||||
@ -39,12 +45,7 @@ import {
|
|||||||
WalletBox,
|
WalletBox,
|
||||||
} from "../components/styled/index.js";
|
} from "../components/styled/index.js";
|
||||||
import { AlertProvider } from "../context/alert.js";
|
import { AlertProvider } from "../context/alert.js";
|
||||||
import { DevContextProvider } from "../context/devContext.js";
|
|
||||||
import { IoCProviderForRuntime } from "../context/iocContext.js";
|
import { IoCProviderForRuntime } from "../context/iocContext.js";
|
||||||
import {
|
|
||||||
TranslationProvider,
|
|
||||||
useTranslationContext,
|
|
||||||
} from "@gnu-taler/web-util/lib/index.browser";
|
|
||||||
import { DepositPage as DepositPageCTA } from "../cta/Deposit/index.js";
|
import { DepositPage as DepositPageCTA } from "../cta/Deposit/index.js";
|
||||||
import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
|
import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
|
||||||
import { InvoicePayPage } from "../cta/InvoicePay/index.js";
|
import { InvoicePayPage } from "../cta/InvoicePay/index.js";
|
||||||
@ -59,12 +60,7 @@ import {
|
|||||||
WithdrawPageFromParams,
|
WithdrawPageFromParams,
|
||||||
WithdrawPageFromURI,
|
WithdrawPageFromURI,
|
||||||
} from "../cta/Withdraw/index.js";
|
} from "../cta/Withdraw/index.js";
|
||||||
import {
|
import { strings } from "../i18n/strings.js";
|
||||||
Pages,
|
|
||||||
WalletNavBar,
|
|
||||||
WalletNavBarOptions,
|
|
||||||
getPathnameForTalerURI,
|
|
||||||
} from "../NavigationBar.js";
|
|
||||||
import { platform } from "../platform/foreground.js";
|
import { platform } from "../platform/foreground.js";
|
||||||
import CloseIcon from "../svg/close_24px.svg";
|
import CloseIcon from "../svg/close_24px.svg";
|
||||||
import { AddBackupProviderPage } from "./AddBackupProvider/index.js";
|
import { AddBackupProviderPage } from "./AddBackupProvider/index.js";
|
||||||
@ -80,7 +76,6 @@ import { QrReaderPage } from "./QrReader.js";
|
|||||||
import { SettingsPage } from "./Settings.js";
|
import { SettingsPage } from "./Settings.js";
|
||||||
import { TransactionPage } from "./Transaction.js";
|
import { TransactionPage } from "./Transaction.js";
|
||||||
import { WelcomePage } from "./Welcome.js";
|
import { WelcomePage } from "./Welcome.js";
|
||||||
import { strings } from "../i18n/strings.js";
|
|
||||||
|
|
||||||
export function Application(): VNode {
|
export function Application(): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
@ -91,7 +86,6 @@ export function Application(): VNode {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TranslationProvider source={strings}>
|
<TranslationProvider source={strings}>
|
||||||
<DevContextProvider>
|
|
||||||
<IoCProviderForRuntime>
|
<IoCProviderForRuntime>
|
||||||
<Router history={hash_history}>
|
<Router history={hash_history}>
|
||||||
<Route
|
<Route
|
||||||
@ -147,10 +141,7 @@ export function Application(): VNode {
|
|||||||
<Route
|
<Route
|
||||||
path={Pages.balanceHistory.pattern}
|
path={Pages.balanceHistory.pattern}
|
||||||
component={({ currency }: { currency?: string }) => (
|
component={({ currency }: { currency?: string }) => (
|
||||||
<WalletTemplate
|
<WalletTemplate path="balance" goToTransaction={redirectToTxInfo}>
|
||||||
path="balance"
|
|
||||||
goToTransaction={redirectToTxInfo}
|
|
||||||
>
|
|
||||||
<HistoryPage
|
<HistoryPage
|
||||||
currency={currency}
|
currency={currency}
|
||||||
goToWalletDeposit={(currency: string) =>
|
goToWalletDeposit={(currency: string) =>
|
||||||
@ -236,10 +227,7 @@ export function Application(): VNode {
|
|||||||
<Route
|
<Route
|
||||||
path={Pages.backup}
|
path={Pages.backup}
|
||||||
component={() => (
|
component={() => (
|
||||||
<WalletTemplate
|
<WalletTemplate path="backup" goToTransaction={redirectToTxInfo}>
|
||||||
path="backup"
|
|
||||||
goToTransaction={redirectToTxInfo}
|
|
||||||
>
|
|
||||||
<BackupPage
|
<BackupPage
|
||||||
onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
|
onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
|
||||||
/>
|
/>
|
||||||
@ -487,11 +475,7 @@ export function Application(): VNode {
|
|||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.ctaRecovery}
|
path={Pages.ctaRecovery}
|
||||||
component={({
|
component={({ talerRecoveryUri }: { talerRecoveryUri: string }) => (
|
||||||
talerRecoveryUri,
|
|
||||||
}: {
|
|
||||||
talerRecoveryUri: string;
|
|
||||||
}) => (
|
|
||||||
<CallToActionTemplate title={i18n.str`Digital cash recovery`}>
|
<CallToActionTemplate title={i18n.str`Digital cash recovery`}>
|
||||||
<RecoveryPage
|
<RecoveryPage
|
||||||
talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
|
talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
|
||||||
@ -517,7 +501,6 @@ export function Application(): VNode {
|
|||||||
/>
|
/>
|
||||||
</Router>
|
</Router>
|
||||||
</IoCProviderForRuntime>
|
</IoCProviderForRuntime>
|
||||||
</DevContextProvider>
|
|
||||||
</TranslationProvider>
|
</TranslationProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { styled } from "@linaria/react";
|
import { styled } from "@linaria/react";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { AmountField } from "../../components/AmountField.js";
|
import { AmountField } from "../../components/AmountField.js";
|
||||||
import { JustInDevMode } from "../../components/JustInDevMode.js";
|
import { EnabledBySettings } from "../../components/EnabledBySettings.js";
|
||||||
import { SelectList } from "../../components/SelectList.js";
|
import { SelectList } from "../../components/SelectList.js";
|
||||||
import {
|
import {
|
||||||
Input,
|
Input,
|
||||||
@ -300,11 +300,11 @@ export function ReadySendView({
|
|||||||
required
|
required
|
||||||
handler={amountHandler}
|
handler={amountHandler}
|
||||||
/>
|
/>
|
||||||
<JustInDevMode>
|
<EnabledBySettings name="advanceMode">
|
||||||
<Button onClick={sendAll.onClick}>
|
<Button onClick={sendAll.onClick}>
|
||||||
<i18n.Translate>Send all</i18n.Translate>
|
<i18n.Translate>Send all</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid container spacing={1} columns={1}>
|
<Grid container spacing={1} columns={1}>
|
||||||
|
@ -23,10 +23,10 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
|||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
import { alertFromError, useAlertContext } from "../../context/alert.js";
|
||||||
import { useBackendContext } from "../../context/backend.js";
|
import { useBackendContext } from "../../context/backend.js";
|
||||||
import { useDevContext } from "../../context/devContext.js";
|
|
||||||
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
||||||
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
|
||||||
import { AccountByType, Props, State } from "./index.js";
|
import { AccountByType, Props, State } from "./index.js";
|
||||||
|
import { useSettings } from "../../hooks/useSettings.js";
|
||||||
|
|
||||||
export function useComponentState({
|
export function useComponentState({
|
||||||
currency,
|
currency,
|
||||||
@ -39,12 +39,11 @@ export function useComponentState({
|
|||||||
const hook = useAsyncAsHook(() =>
|
const hook = useAsyncAsHook(() =>
|
||||||
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
|
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
|
||||||
);
|
);
|
||||||
const { devMode } = useDevContext();
|
|
||||||
const accountType: Record<string, string> = {
|
const accountType: Record<string, string> = {
|
||||||
iban: "IBAN",
|
iban: "IBAN",
|
||||||
// "x-taler-bank": "Taler Bank",
|
|
||||||
};
|
};
|
||||||
if (devMode) {
|
const [settings] = useSettings();
|
||||||
|
if (settings.extendedAccountTypes) {
|
||||||
accountType["bitcoin"] = "Bitcoin";
|
accountType["bitcoin"] = "Bitcoin";
|
||||||
accountType["x-taler-bank"] = "Taler Bank";
|
accountType["x-taler-bank"] = "Taler Bank";
|
||||||
}
|
}
|
||||||
|
@ -47,27 +47,27 @@ const version = {
|
|||||||
|
|
||||||
export const AllOff = tests.createExample(TestedComponent, {
|
export const AllOff = tests.createExample(TestedComponent, {
|
||||||
deviceName: "this-is-the-device-name",
|
deviceName: "this-is-the-device-name",
|
||||||
devModeToggle: { value: false, button: {} },
|
advanceToggle: { value: false, button: {} },
|
||||||
autoOpenToggle: { value: false, button: {} },
|
autoOpenToggle: { value: false, button: {} },
|
||||||
clipboardToggle: { value: false, button: {} },
|
langToggle: { value: false, button: {} },
|
||||||
setDeviceName: () => Promise.resolve(),
|
setDeviceName: () => Promise.resolve(),
|
||||||
...version,
|
...version,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const OneChecked = tests.createExample(TestedComponent, {
|
export const OneChecked = tests.createExample(TestedComponent, {
|
||||||
deviceName: "this-is-the-device-name",
|
deviceName: "this-is-the-device-name",
|
||||||
devModeToggle: { value: false, button: {} },
|
advanceToggle: { value: false, button: {} },
|
||||||
autoOpenToggle: { value: false, button: {} },
|
autoOpenToggle: { value: false, button: {} },
|
||||||
clipboardToggle: { value: false, button: {} },
|
langToggle: { value: false, button: {} },
|
||||||
setDeviceName: () => Promise.resolve(),
|
setDeviceName: () => Promise.resolve(),
|
||||||
...version,
|
...version,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const WithOneExchange = tests.createExample(TestedComponent, {
|
export const WithOneExchange = tests.createExample(TestedComponent, {
|
||||||
deviceName: "this-is-the-device-name",
|
deviceName: "this-is-the-device-name",
|
||||||
devModeToggle: { value: false, button: {} },
|
advanceToggle: { value: false, button: {} },
|
||||||
autoOpenToggle: { value: false, button: {} },
|
autoOpenToggle: { value: false, button: {} },
|
||||||
clipboardToggle: { value: false, button: {} },
|
langToggle: { value: false, button: {} },
|
||||||
setDeviceName: () => Promise.resolve(),
|
setDeviceName: () => Promise.resolve(),
|
||||||
knownExchanges: [
|
knownExchanges: [
|
||||||
{
|
{
|
||||||
@ -89,9 +89,9 @@ export const WithExchangeInDifferentState = tests.createExample(
|
|||||||
TestedComponent,
|
TestedComponent,
|
||||||
{
|
{
|
||||||
deviceName: "this-is-the-device-name",
|
deviceName: "this-is-the-device-name",
|
||||||
devModeToggle: { value: false, button: {} },
|
advanceToggle: { value: false, button: {} },
|
||||||
autoOpenToggle: { value: false, button: {} },
|
autoOpenToggle: { value: false, button: {} },
|
||||||
clipboardToggle: { value: false, button: {} },
|
langToggle: { value: false, button: {} },
|
||||||
setDeviceName: () => Promise.resolve(),
|
setDeviceName: () => Promise.resolve(),
|
||||||
knownExchanges: [
|
knownExchanges: [
|
||||||
{
|
{
|
||||||
|
@ -17,12 +17,15 @@
|
|||||||
import {
|
import {
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
ExchangeTosStatus,
|
ExchangeTosStatus,
|
||||||
|
TranslatedString,
|
||||||
WalletCoreVersion,
|
WalletCoreVersion,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
||||||
|
import { Fragment, VNode, h } from "preact";
|
||||||
|
import { Pages } from "../NavigationBar.js";
|
||||||
import { Checkbox } from "../components/Checkbox.js";
|
import { Checkbox } from "../components/Checkbox.js";
|
||||||
import { JustInDevMode } from "../components/JustInDevMode.js";
|
import { EnabledBySettings } from "../components/EnabledBySettings.js";
|
||||||
import { Part } from "../components/Part.js";
|
import { Part } from "../components/Part.js";
|
||||||
import { SelectList } from "../components/SelectList.js";
|
import { SelectList } from "../components/SelectList.js";
|
||||||
import {
|
import {
|
||||||
@ -35,25 +38,20 @@ import {
|
|||||||
} from "../components/styled/index.js";
|
} from "../components/styled/index.js";
|
||||||
import { useAlertContext } from "../context/alert.js";
|
import { useAlertContext } from "../context/alert.js";
|
||||||
import { useBackendContext } from "../context/backend.js";
|
import { useBackendContext } from "../context/backend.js";
|
||||||
import { useDevContext } from "../context/devContext.js";
|
|
||||||
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||||
import { useSettings } from "../hooks/useSettings.js";
|
|
||||||
import { useBackupDeviceName } from "../hooks/useBackupDeviceName.js";
|
import { useBackupDeviceName } from "../hooks/useBackupDeviceName.js";
|
||||||
import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js";
|
import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js";
|
||||||
|
import { useSettings } from "../hooks/useSettings.js";
|
||||||
import { ToggleHandler } from "../mui/handlers.js";
|
import { ToggleHandler } from "../mui/handlers.js";
|
||||||
import { Pages } from "../NavigationBar.js";
|
|
||||||
import { platform } from "../platform/foreground.js";
|
import { platform } from "../platform/foreground.js";
|
||||||
|
import { Settings } from "../platform/api.js";
|
||||||
|
|
||||||
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
|
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
|
||||||
|
|
||||||
export function SettingsPage(): VNode {
|
export function SettingsPage(): VNode {
|
||||||
const [settings, updateSettings] = useSettings();
|
const [settings, updateSettings] = useSettings();
|
||||||
const clipboardToggle = useClipboardPermissions();
|
|
||||||
const { devMode, toggle } = useDevContext();
|
|
||||||
const { safely } = useAlertContext();
|
const { safely } = useAlertContext();
|
||||||
const { name, update } = useBackupDeviceName();
|
const { name, update } = useBackupDeviceName();
|
||||||
const { pushAlertOnError } = useAlertContext();
|
|
||||||
const webex = platform.getWalletWebExVersion();
|
const webex = platform.getWalletWebExVersion();
|
||||||
const api = useBackendContext();
|
const api = useBackendContext();
|
||||||
|
|
||||||
@ -76,16 +74,24 @@ export function SettingsPage(): VNode {
|
|||||||
value: settings.injectTalerSupport,
|
value: settings.injectTalerSupport,
|
||||||
button: {
|
button: {
|
||||||
onClick: safely("update support injection", async () => {
|
onClick: safely("update support injection", async () => {
|
||||||
console.log("click", settings.injectTalerSupport);
|
|
||||||
updateSettings("injectTalerSupport", !settings.injectTalerSupport);
|
updateSettings("injectTalerSupport", !settings.injectTalerSupport);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
clipboardToggle={clipboardToggle}
|
advanceToggle={{
|
||||||
devModeToggle={{
|
value: settings.advanceMode,
|
||||||
value: devMode,
|
|
||||||
button: {
|
button: {
|
||||||
onClick: pushAlertOnError(toggle),
|
onClick: safely("update advance mode", async () => {
|
||||||
|
updateSettings("advanceMode", !settings.advanceMode);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
langToggle={{
|
||||||
|
value: settings.langSelector,
|
||||||
|
button: {
|
||||||
|
onClick: safely("update lang selector", async () => {
|
||||||
|
updateSettings("langSelector", !settings.langSelector);
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
webexVersion={{
|
webexVersion={{
|
||||||
@ -101,8 +107,8 @@ export interface ViewProps {
|
|||||||
deviceName: string;
|
deviceName: string;
|
||||||
setDeviceName: (s: string) => Promise<void>;
|
setDeviceName: (s: string) => Promise<void>;
|
||||||
autoOpenToggle: ToggleHandler;
|
autoOpenToggle: ToggleHandler;
|
||||||
clipboardToggle: ToggleHandler;
|
advanceToggle: ToggleHandler;
|
||||||
devModeToggle: ToggleHandler;
|
langToggle: ToggleHandler;
|
||||||
knownExchanges: Array<ExchangeListItem>;
|
knownExchanges: Array<ExchangeListItem>;
|
||||||
coreVersion: WalletCoreVersion | undefined;
|
coreVersion: WalletCoreVersion | undefined;
|
||||||
webexVersion: {
|
webexVersion: {
|
||||||
@ -114,8 +120,8 @@ export interface ViewProps {
|
|||||||
export function SettingsView({
|
export function SettingsView({
|
||||||
knownExchanges,
|
knownExchanges,
|
||||||
autoOpenToggle,
|
autoOpenToggle,
|
||||||
clipboardToggle,
|
advanceToggle,
|
||||||
devModeToggle,
|
langToggle,
|
||||||
coreVersion,
|
coreVersion,
|
||||||
webexVersion,
|
webexVersion,
|
||||||
}: ViewProps): VNode {
|
}: ViewProps): VNode {
|
||||||
@ -204,45 +210,19 @@ export function SettingsView({
|
|||||||
</LinkPrimary>
|
</LinkPrimary>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<JustInDevMode>
|
|
||||||
<SubTitle>
|
|
||||||
<i18n.Translate>Display</i18n.Translate>
|
|
||||||
</SubTitle>
|
|
||||||
<Input>
|
|
||||||
<SelectList
|
|
||||||
label={<i18n.Translate>Current Language</i18n.Translate>}
|
|
||||||
list={supportedLang}
|
|
||||||
name="lang"
|
|
||||||
value={lang}
|
|
||||||
onChange={(v) => changeLanguage(v)}
|
|
||||||
/>
|
|
||||||
</Input>
|
|
||||||
</JustInDevMode>
|
|
||||||
<SubTitle>
|
|
||||||
<i18n.Translate>Version</i18n.Translate>
|
|
||||||
</SubTitle>
|
|
||||||
{coreVersion && (
|
|
||||||
<Part
|
|
||||||
title={i18n.str`Wallet Core`}
|
|
||||||
text={
|
|
||||||
<span>
|
|
||||||
{coreVersion.version}{" "}
|
|
||||||
<JustInDevMode>{coreVersion.hash}</JustInDevMode>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Part
|
<Part
|
||||||
title={i18n.str`Web Extension`}
|
title={i18n.str`Web Extension`}
|
||||||
text={
|
text={
|
||||||
<span>
|
<span>
|
||||||
{webexVersion.version}{" "}
|
{webexVersion.version}{" "}
|
||||||
<JustInDevMode>{webexVersion.hash}</JustInDevMode>
|
<EnabledBySettings name="advanceMode">
|
||||||
|
{webexVersion.hash}
|
||||||
|
</EnabledBySettings>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{coreVersion && (
|
{coreVersion && (
|
||||||
<JustInDevMode>
|
<EnabledBySettings name="advanceMode">
|
||||||
<Part
|
<Part
|
||||||
title={i18n.str`Exchange compatibility`}
|
title={i18n.str`Exchange compatibility`}
|
||||||
text={<span>{coreVersion.exchange}</span>}
|
text={<span>{coreVersion.exchange}</span>}
|
||||||
@ -255,18 +235,42 @@ export function SettingsView({
|
|||||||
title={i18n.str`Bank compatibility`}
|
title={i18n.str`Bank compatibility`}
|
||||||
text={<span>{coreVersion.bank}</span>}
|
text={<span>{coreVersion.bank}</span>}
|
||||||
/>
|
/>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
)}
|
)}
|
||||||
<SubTitle>
|
<SubTitle>
|
||||||
<i18n.Translate>Troubleshooting</i18n.Translate>
|
<i18n.Translate>Advance mode</i18n.Translate>
|
||||||
</SubTitle>
|
</SubTitle>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={i18n.str`Developer mode`}
|
label={i18n.str`Enable advance mode`}
|
||||||
name="devMode"
|
name="devMode"
|
||||||
description={i18n.str`More options and information useful for debugging`}
|
description={i18n.str`Show more information and options in the UI`}
|
||||||
enabled={devModeToggle.value!}
|
enabled={advanceToggle.value!}
|
||||||
onToggle={devModeToggle.button.onClick!}
|
onToggle={advanceToggle.button.onClick!}
|
||||||
/>
|
/>
|
||||||
|
<EnabledBySettings name="advanceMode">
|
||||||
|
<AdvanceSettings />
|
||||||
|
</EnabledBySettings>
|
||||||
|
<Checkbox
|
||||||
|
label={i18n.str`Lang selector`}
|
||||||
|
name="langSelector"
|
||||||
|
description={i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`}
|
||||||
|
enabled={langToggle.value!}
|
||||||
|
onToggle={langToggle.button.onClick!}
|
||||||
|
/>
|
||||||
|
<EnabledBySettings name="langSelector">
|
||||||
|
<SubTitle>
|
||||||
|
<i18n.Translate>Display</i18n.Translate>
|
||||||
|
</SubTitle>
|
||||||
|
<Input>
|
||||||
|
<SelectList
|
||||||
|
label={<i18n.Translate>Current Language</i18n.Translate>}
|
||||||
|
list={supportedLang}
|
||||||
|
name="lang"
|
||||||
|
value={lang}
|
||||||
|
onChange={(v) => changeLanguage(v)}
|
||||||
|
/>
|
||||||
|
</Input>
|
||||||
|
</EnabledBySettings>
|
||||||
<SubTitle>
|
<SubTitle>
|
||||||
<i18n.Translate>Navigator</i18n.Translate>
|
<i18n.Translate>Navigator</i18n.Translate>
|
||||||
</SubTitle>
|
</SubTitle>
|
||||||
@ -283,6 +287,77 @@ export function SettingsView({
|
|||||||
enabled={autoOpenToggle.value!}
|
enabled={autoOpenToggle.value!}
|
||||||
onToggle={autoOpenToggle.button.onClick!}
|
onToggle={autoOpenToggle.button.onClick!}
|
||||||
/>
|
/>
|
||||||
|
<SubTitle>
|
||||||
|
<i18n.Translate>Version</i18n.Translate>
|
||||||
|
</SubTitle>
|
||||||
|
{coreVersion && (
|
||||||
|
<Part
|
||||||
|
title={i18n.str`Wallet Core`}
|
||||||
|
text={
|
||||||
|
<span>
|
||||||
|
{coreVersion.version}{" "}
|
||||||
|
<EnabledBySettings name="advanceMode">
|
||||||
|
{coreVersion.hash}
|
||||||
|
</EnabledBySettings>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type Info = { label: TranslatedString; description: TranslatedString };
|
||||||
|
type Options = {
|
||||||
|
[k in keyof Settings]?: Info;
|
||||||
|
};
|
||||||
|
function AdvanceSettings(): VNode {
|
||||||
|
const [settings, updateSettings] = useSettings();
|
||||||
|
const { i18n } = useTranslationContext();
|
||||||
|
const o: Options = {
|
||||||
|
backup: {
|
||||||
|
label: i18n.str`Show backup feature`,
|
||||||
|
description: i18n.str`Backup integration still in beta.`,
|
||||||
|
},
|
||||||
|
deleteActiveTransactions: {
|
||||||
|
label: i18n.str`Show delete active transaction`,
|
||||||
|
description: i18n.str`Deleting active transaction is not safe and you may loose your coins.`,
|
||||||
|
},
|
||||||
|
extendedAccountTypes: {
|
||||||
|
label: i18n.str`Show more account types on deposit`,
|
||||||
|
description: i18n.str`Extends the UI to more payment target types.`,
|
||||||
|
},
|
||||||
|
showJsonOnError: {
|
||||||
|
label: i18n.str`Show JSON on error`,
|
||||||
|
description: i18n.str`Print more information about the error. Useful for debugging.`,
|
||||||
|
},
|
||||||
|
walletAllowHttp: {
|
||||||
|
label: i18n.str`Allow HTTP connections`,
|
||||||
|
description: i18n.str`Using HTTP connection may be faster but unsafe (wallet restart required)`,
|
||||||
|
},
|
||||||
|
walletBatchWithdrawal: {
|
||||||
|
label: i18n.str`Allow batch withdrawals`,
|
||||||
|
description: i18n.str`Using the batch withdrawal API allows faster withdrawals (wallet restart required)`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<section>
|
||||||
|
{Object.entries(o).map(([name, { label, description }]) => {
|
||||||
|
const settingsName = name as keyof Settings;
|
||||||
|
return (
|
||||||
|
<Checkbox
|
||||||
|
label={label}
|
||||||
|
name={name}
|
||||||
|
description={description}
|
||||||
|
enabled={settings[settingsName]}
|
||||||
|
onToggle={async () => {
|
||||||
|
updateSettings(settingsName, !settings[settingsName]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</section>
|
</section>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -34,6 +34,7 @@ import {
|
|||||||
WithdrawalType,
|
WithdrawalType,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
|
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
||||||
import { styled } from "@linaria/react";
|
import { styled } from "@linaria/react";
|
||||||
import { differenceInSeconds, isPast } from "date-fns";
|
import { differenceInSeconds, isPast } from "date-fns";
|
||||||
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
import { ComponentChildren, Fragment, h, VNode } from "preact";
|
||||||
@ -43,7 +44,6 @@ import { Amount } from "../components/Amount.js";
|
|||||||
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType.js";
|
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType.js";
|
||||||
import { CopyButton } from "../components/CopyButton.js";
|
import { CopyButton } from "../components/CopyButton.js";
|
||||||
import { AlertView, ErrorAlertView } from "../components/CurrentAlerts.js";
|
import { AlertView, ErrorAlertView } from "../components/CurrentAlerts.js";
|
||||||
import { JustInDevMode } from "../components/JustInDevMode.js";
|
|
||||||
import { Loading } from "../components/Loading.js";
|
import { Loading } from "../components/Loading.js";
|
||||||
import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
|
import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
|
||||||
import { QR } from "../components/QR.js";
|
import { QR } from "../components/QR.js";
|
||||||
@ -61,12 +61,12 @@ import {
|
|||||||
import { Time } from "../components/Time.js";
|
import { Time } from "../components/Time.js";
|
||||||
import { alertFromError, useAlertContext } from "../context/alert.js";
|
import { alertFromError, useAlertContext } from "../context/alert.js";
|
||||||
import { useBackendContext } from "../context/backend.js";
|
import { useBackendContext } from "../context/backend.js";
|
||||||
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
|
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||||
import { Button } from "../mui/Button.js";
|
import { Button } from "../mui/Button.js";
|
||||||
import { SafeHandler } from "../mui/handlers.js";
|
import { SafeHandler } from "../mui/handlers.js";
|
||||||
import { Pages } from "../NavigationBar.js";
|
import { Pages } from "../NavigationBar.js";
|
||||||
import { assertUnreachable } from "../utils/index.js";
|
import { assertUnreachable } from "../utils/index.js";
|
||||||
|
import { EnabledBySettings } from "../components/EnabledBySettings.js";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tid: string;
|
tid: string;
|
||||||
@ -359,18 +359,15 @@ function TransactionTemplate({
|
|||||||
<i18n.Translate>Cancel</i18n.Translate>
|
<i18n.Translate>Cancel</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
//WORKAROUND
|
<EnabledBySettings name="deleteActiveTransactions">
|
||||||
//Able to delete tx in dev mode
|
|
||||||
//FIXME: remove this when DD37 is implemented
|
|
||||||
<JustInDevMode>
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="error"
|
color="error"
|
||||||
onClick={doCheckBeforeForget as SafeHandler<void>}
|
onClick={doCheckBeforeForget as SafeHandler<void>}
|
||||||
>
|
>
|
||||||
<i18n.Translate>Forget</i18n.Translate>
|
<i18n.Translate>Delete</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
</JustInDevMode>
|
</EnabledBySettings>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
@ -378,7 +375,7 @@ function TransactionTemplate({
|
|||||||
color="error"
|
color="error"
|
||||||
onClick={doCheckBeforeForget as SafeHandler<void>}
|
onClick={doCheckBeforeForget as SafeHandler<void>}
|
||||||
>
|
>
|
||||||
<i18n.Translate>Forget</i18n.Translate>
|
<i18n.Translate>Delete</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,6 @@ import { setupPlatform } from "./platform/foreground.js";
|
|||||||
import devAPI from "./platform/dev.js";
|
import devAPI from "./platform/dev.js";
|
||||||
import { Application } from "./wallet/Application.js";
|
import { Application } from "./wallet/Application.js";
|
||||||
|
|
||||||
console.log("Wallet setup for Dev API");
|
|
||||||
setupPlatform(devAPI);
|
setupPlatform(devAPI);
|
||||||
|
|
||||||
function main(): void {
|
function main(): void {
|
||||||
|
@ -33,10 +33,8 @@ const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
|
|||||||
//FIXME: create different entry point for any platform instead of
|
//FIXME: create different entry point for any platform instead of
|
||||||
//switching in runtime
|
//switching in runtime
|
||||||
if (isFirefox) {
|
if (isFirefox) {
|
||||||
console.log("Wallet setup for Firefox API");
|
|
||||||
setupPlatform(firefoxAPI);
|
setupPlatform(firefoxAPI);
|
||||||
} else {
|
} else {
|
||||||
console.log("Wallet setup for Chrome API");
|
|
||||||
setupPlatform(chromeAPI);
|
setupPlatform(chromeAPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ class WalletApiClientImpl implements WalletCoreApiClient {
|
|||||||
};
|
};
|
||||||
response = await platform.sendMessageToBackground(message);
|
response = await platform.sendMessageToBackground(message);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error calling backend");
|
logger.error("Error calling backend", e);
|
||||||
throw new Error(`Error contacting backend: ${e}`);
|
throw new Error(`Error contacting backend: ${e}`);
|
||||||
}
|
}
|
||||||
if (response.type === "error") {
|
if (response.type === "error") {
|
||||||
|
@ -319,12 +319,19 @@ async function reinitWallet(): Promise<void> {
|
|||||||
timer = new SetTimeoutTimerAPI();
|
timer = new SetTimeoutTimerAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settings = await platform.getSettingsFromStorage();
|
||||||
logger.info("Setting up wallet");
|
logger.info("Setting up wallet");
|
||||||
const wallet = await Wallet.create(
|
const wallet = await Wallet.create(
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
httpLib,
|
httpLib,
|
||||||
timer,
|
timer,
|
||||||
cryptoWorker,
|
cryptoWorker,
|
||||||
|
{
|
||||||
|
features: {
|
||||||
|
allowHttp: settings.walletAllowHttp,
|
||||||
|
batchWithdrawal: settings.walletBatchWithdrawal,
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
await wallet.handleCoreApiRequest("initWallet", "native-init", {});
|
await wallet.handleCoreApiRequest("initWallet", "native-init", {});
|
||||||
|
Loading…
Reference in New Issue
Block a user