more lint fixes
This commit is contained in:
parent
1471aae892
commit
fb2e2f8993
@ -7,6 +7,7 @@ module.exports = {
|
|||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:react/recommended",
|
"plugin:react/recommended",
|
||||||
|
"plugin:react-hooks/recommended",
|
||||||
],
|
],
|
||||||
settings: {
|
settings: {
|
||||||
"react": {
|
"react": {
|
||||||
@ -18,6 +19,7 @@ module.exports = {
|
|||||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||||
"prefer-const": ["warn", { destructuring: "all" }],
|
"prefer-const": ["warn", { destructuring: "all" }],
|
||||||
"@typescript-eslint/camelcase": "off",
|
"@typescript-eslint/camelcase": "off",
|
||||||
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
|
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
|
||||||
"@typescript-eslint/explicit-function-return-type": [
|
"@typescript-eslint/explicit-function-return-type": [
|
||||||
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -34,7 +34,6 @@
|
|||||||
},
|
},
|
||||||
"**/*.js.map": true
|
"**/*.js.map": true
|
||||||
},
|
},
|
||||||
"tslint.enable": true,
|
|
||||||
"editor.wrappingIndent": "same",
|
"editor.wrappingIndent": "same",
|
||||||
"editor.tabSize": 2
|
"editor.tabSize": 2
|
||||||
}
|
}
|
2
Makefile
2
Makefile
@ -82,4 +82,4 @@ rollup: tsc
|
|||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
./node_modules/.bin/eslint 'src/**/*' --ext '.js,.ts,.tsx'
|
./node_modules/.bin/eslint --ext '.js,.ts,.tsx' 'src'
|
||||||
|
@ -40,7 +40,9 @@
|
|||||||
"@typescript-eslint/parser": "^2.26.0",
|
"@typescript-eslint/parser": "^2.26.0",
|
||||||
"ava": "^3.6.0",
|
"ava": "^3.6.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-airbnb-typescript": "^7.2.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
"eslint-plugin-react": "^7.19.0",
|
"eslint-plugin-react": "^7.19.0",
|
||||||
"eslint-plugin-react-hooks": "^3.0.0",
|
"eslint-plugin-react-hooks": "^3.0.0",
|
||||||
"jed": "^1.1.1",
|
"jed": "^1.1.1",
|
||||||
|
@ -32,7 +32,6 @@ import {
|
|||||||
Headers,
|
Headers,
|
||||||
} from "../util/http";
|
} from "../util/http";
|
||||||
import { NodeHttpLib } from "../headless/NodeHttpLib";
|
import { NodeHttpLib } from "../headless/NodeHttpLib";
|
||||||
import { OperationFailedAndReportedError } from "../operations/errors";
|
|
||||||
import { WalletNotification } from "../types/notifications";
|
import { WalletNotification } from "../types/notifications";
|
||||||
|
|
||||||
// @ts-ignore: special built-in module
|
// @ts-ignore: special built-in module
|
||||||
@ -99,7 +98,7 @@ export class AndroidHttpLib implements HttpRequestLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTunnelResponse(msg: any) {
|
handleTunnelResponse(msg: any): void {
|
||||||
const myId = msg.id;
|
const myId = msg.id;
|
||||||
const p = this.requestMap[myId];
|
const p = this.requestMap[myId];
|
||||||
if (!p) {
|
if (!p) {
|
||||||
@ -123,7 +122,7 @@ export class AndroidHttpLib implements HttpRequestLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAkonoMessage(m: string) {
|
function sendAkonoMessage(m: string): void {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
globalThis.__akono_sendMessage(m);
|
globalThis.__akono_sendMessage(m);
|
||||||
}
|
}
|
||||||
@ -266,7 +265,7 @@ class AndroidWalletMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function installAndroidWalletListener() {
|
export function installAndroidWalletListener(): void {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const sendMessage: (m: string) => void = globalThis.__akono_sendMessage;
|
const sendMessage: (m: string) => void = globalThis.__akono_sendMessage;
|
||||||
if (typeof sendMessage !== "function") {
|
if (typeof sendMessage !== "function") {
|
||||||
@ -276,7 +275,7 @@ export function installAndroidWalletListener() {
|
|||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
const handler = new AndroidWalletMessageHandler();
|
const handler = new AndroidWalletMessageHandler();
|
||||||
const onMessage = async (msgStr: any) => {
|
const onMessage = async (msgStr: any): Promise<void> => {
|
||||||
if (typeof msgStr !== "string") {
|
if (typeof msgStr !== "string") {
|
||||||
console.error("expected string as message");
|
console.error("expected string as message");
|
||||||
return;
|
return;
|
||||||
|
@ -51,11 +51,11 @@ export function hmac(
|
|||||||
return digest(b2);
|
return digest(b2);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hmacSha512(key: Uint8Array, message: Uint8Array) {
|
export function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {
|
||||||
return hmac(sha512, 128, key, message);
|
return hmac(sha512, 128, key, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hmacSha256(key: Uint8Array, message: Uint8Array) {
|
export function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {
|
||||||
return hmac(sha256, 64, key, message);
|
return hmac(sha256, 64, key, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ export class HashSha256 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleans internal buffers and re-initializes hash state.
|
// Cleans internal buffers and re-initializes hash state.
|
||||||
clean() {
|
clean(): void {
|
||||||
for (let i = 0; i < this.buffer.length; i++) {
|
for (let i = 0; i < this.buffer.length; i++) {
|
||||||
this.buffer[i] = 0;
|
this.buffer[i] = 0;
|
||||||
}
|
}
|
||||||
@ -306,14 +306,14 @@ export class HashSha256 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal function for use in HMAC for optimization.
|
// Internal function for use in HMAC for optimization.
|
||||||
_saveState(out: Uint32Array) {
|
_saveState(out: Uint32Array): void {
|
||||||
for (let i = 0; i < this.state.length; i++) {
|
for (let i = 0; i < this.state.length; i++) {
|
||||||
out[i] = this.state[i];
|
out[i] = this.state[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal function for use in HMAC for optimization.
|
// Internal function for use in HMAC for optimization.
|
||||||
_restoreState(from: Uint32Array, bytesHashed: number) {
|
_restoreState(from: Uint32Array, bytesHashed: number): void {
|
||||||
for (let i = 0; i < this.state.length; i++) {
|
for (let i = 0; i < this.state.length; i++) {
|
||||||
this.state[i] = from[i];
|
this.state[i] = from[i];
|
||||||
}
|
}
|
||||||
@ -376,7 +376,7 @@ export class HMAC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleans HMAC state.
|
// Cleans HMAC state.
|
||||||
clean() {
|
clean(): void {
|
||||||
for (let i = 0; i < this.istate.length; i++) {
|
for (let i = 0; i < this.istate.length; i++) {
|
||||||
this.ostate[i] = this.istate[i] = 0;
|
this.ostate[i] = this.istate[i] = 0;
|
||||||
}
|
}
|
||||||
@ -418,7 +418,7 @@ export function sha256(data: Uint8Array): Uint8Array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns HMAC-SHA256 of data under the key.
|
// Returns HMAC-SHA256 of data under the key.
|
||||||
export function hmacSha256(key: Uint8Array, data: Uint8Array) {
|
export function hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array {
|
||||||
const h = new HMAC(key).update(data);
|
const h = new HMAC(key).update(data);
|
||||||
const digest = h.digest();
|
const digest = h.digest();
|
||||||
h.clean();
|
h.clean();
|
||||||
|
@ -191,12 +191,12 @@ function kdfMod(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stringToBytes(s: string) {
|
export function stringToBytes(s: string): Uint8Array {
|
||||||
const te = new TextEncoder();
|
const te = new TextEncoder();
|
||||||
return te.encode(s);
|
return te.encode(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadBigInt(arr: Uint8Array) {
|
function loadBigInt(arr: Uint8Array): bigint.BigInteger {
|
||||||
return bigint.fromArray(Array.from(arr), 256, false);
|
return bigint.fromArray(Array.from(arr), 256, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ function rsaBlindingKeyDerive(
|
|||||||
* @param r KDF result
|
* @param r KDF result
|
||||||
* @param n RSA modulus of the public key
|
* @param n RSA modulus of the public key
|
||||||
*/
|
*/
|
||||||
function rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger) {
|
function rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger): void {
|
||||||
const t = bigint.gcd(r, n);
|
const t = bigint.gcd(r, n);
|
||||||
if (!t.equals(bigint.one)) {
|
if (!t.equals(bigint.one)) {
|
||||||
throw Error("malicious RSA public key");
|
throw Error("malicious RSA public key");
|
||||||
|
@ -34,13 +34,7 @@ import {
|
|||||||
|
|
||||||
import { CryptoWorker } from "./cryptoWorker";
|
import { CryptoWorker } from "./cryptoWorker";
|
||||||
|
|
||||||
import {
|
import { RecoupRequest, CoinDepositPermission } from "../../types/talerTypes";
|
||||||
RecoupRequest,
|
|
||||||
CoinDepositPermission,
|
|
||||||
RecoupConfirmation,
|
|
||||||
ExchangeSignKeyJson,
|
|
||||||
EddsaPublicKeyString,
|
|
||||||
} from "../../types/talerTypes";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BenchmarkResult,
|
BenchmarkResult,
|
||||||
@ -154,7 +148,7 @@ export class CryptoApi {
|
|||||||
/**
|
/**
|
||||||
* Terminate all worker threads.
|
* Terminate all worker threads.
|
||||||
*/
|
*/
|
||||||
terminateWorkers() {
|
terminateWorkers(): void {
|
||||||
for (const worker of this.workers) {
|
for (const worker of this.workers) {
|
||||||
if (worker.w) {
|
if (worker.w) {
|
||||||
CryptoApi.enableTracing && console.log("terminating worker");
|
CryptoApi.enableTracing && console.log("terminating worker");
|
||||||
@ -172,7 +166,7 @@ export class CryptoApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop(): void {
|
||||||
this.terminateWorkers();
|
this.terminateWorkers();
|
||||||
this.stopped = true;
|
this.stopped = true;
|
||||||
}
|
}
|
||||||
@ -192,11 +186,14 @@ export class CryptoApi {
|
|||||||
}
|
}
|
||||||
ws.currentWorkItem = work;
|
ws.currentWorkItem = work;
|
||||||
this.numBusy++;
|
this.numBusy++;
|
||||||
|
let worker: CryptoWorker;
|
||||||
if (!ws.w) {
|
if (!ws.w) {
|
||||||
const w = this.workerFactory.startWorker();
|
worker = this.workerFactory.startWorker();
|
||||||
w.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m);
|
worker.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m);
|
||||||
w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e);
|
worker.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e);
|
||||||
ws.w = w;
|
ws.w = worker;
|
||||||
|
} else {
|
||||||
|
worker = ws.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg: any = {
|
const msg: any = {
|
||||||
@ -206,28 +203,28 @@ export class CryptoApi {
|
|||||||
};
|
};
|
||||||
this.resetWorkerTimeout(ws);
|
this.resetWorkerTimeout(ws);
|
||||||
work.startTime = timer.performanceNow();
|
work.startTime = timer.performanceNow();
|
||||||
setTimeout(() => ws.w!.postMessage(msg), 0);
|
setTimeout(() => worker.postMessage(msg), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetWorkerTimeout(ws: WorkerState) {
|
resetWorkerTimeout(ws: WorkerState): void {
|
||||||
if (ws.terminationTimerHandle !== null) {
|
if (ws.terminationTimerHandle !== null) {
|
||||||
ws.terminationTimerHandle.clear();
|
ws.terminationTimerHandle.clear();
|
||||||
ws.terminationTimerHandle = null;
|
ws.terminationTimerHandle = null;
|
||||||
}
|
}
|
||||||
const destroy = () => {
|
const destroy = (): void => {
|
||||||
// terminate worker if it's idle
|
// terminate worker if it's idle
|
||||||
if (ws.w && ws.currentWorkItem === null) {
|
if (ws.w && ws.currentWorkItem === null) {
|
||||||
ws.w!.terminate();
|
ws.w.terminate();
|
||||||
ws.w = null;
|
ws.w = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ws.terminationTimerHandle = timer.after(15 * 1000, destroy);
|
ws.terminationTimerHandle = timer.after(15 * 1000, destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWorkerError(ws: WorkerState, e: ErrorEvent) {
|
handleWorkerError(ws: WorkerState, e: ErrorEvent): void {
|
||||||
if (ws.currentWorkItem) {
|
if (ws.currentWorkItem) {
|
||||||
console.error(
|
console.error(
|
||||||
`error in worker during ${ws.currentWorkItem!.operation}`,
|
`error in worker during ${ws.currentWorkItem.operation}`,
|
||||||
e,
|
e,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -235,8 +232,10 @@ export class CryptoApi {
|
|||||||
}
|
}
|
||||||
console.error(e.message);
|
console.error(e.message);
|
||||||
try {
|
try {
|
||||||
ws.w!.terminate();
|
if (ws.w) {
|
||||||
|
ws.w.terminate();
|
||||||
ws.w = null;
|
ws.w = null;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@ -248,19 +247,22 @@ export class CryptoApi {
|
|||||||
this.findWork(ws);
|
this.findWork(ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
private findWork(ws: WorkerState) {
|
private findWork(ws: WorkerState): void {
|
||||||
// try to find more work for this worker
|
// try to find more work for this worker
|
||||||
for (let i = 0; i < NUM_PRIO; i++) {
|
for (let i = 0; i < NUM_PRIO; i++) {
|
||||||
const q = this.workQueues[NUM_PRIO - i - 1];
|
const q = this.workQueues[NUM_PRIO - i - 1];
|
||||||
if (q.length !== 0) {
|
if (q.length !== 0) {
|
||||||
const work: WorkItem = q.shift()!;
|
const work: WorkItem | undefined = q.shift();
|
||||||
|
if (!work) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this.wake(ws, work);
|
this.wake(ws, work);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleWorkerMessage(ws: WorkerState, msg: MessageEvent) {
|
handleWorkerMessage(ws: WorkerState, msg: MessageEvent): void {
|
||||||
const id = msg.data.id;
|
const id = msg.data.id;
|
||||||
if (typeof id !== "number") {
|
if (typeof id !== "number") {
|
||||||
console.error("rpc id must be number");
|
console.error("rpc id must be number");
|
||||||
|
@ -36,13 +36,7 @@ import {
|
|||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
} from "../../types/dbTypes";
|
} from "../../types/dbTypes";
|
||||||
|
|
||||||
import {
|
import { CoinDepositPermission, RecoupRequest } from "../../types/talerTypes";
|
||||||
CoinDepositPermission,
|
|
||||||
RecoupRequest,
|
|
||||||
RecoupConfirmation,
|
|
||||||
ExchangeSignKeyJson,
|
|
||||||
EddsaPublicKeyString,
|
|
||||||
} from "../../types/talerTypes";
|
|
||||||
import {
|
import {
|
||||||
BenchmarkResult,
|
BenchmarkResult,
|
||||||
PlanchetCreationResult,
|
PlanchetCreationResult,
|
||||||
@ -70,11 +64,7 @@ import {
|
|||||||
} from "../talerCrypto";
|
} from "../talerCrypto";
|
||||||
import { randomBytes } from "../primitives/nacl-fast";
|
import { randomBytes } from "../primitives/nacl-fast";
|
||||||
import { kdf } from "../primitives/kdf";
|
import { kdf } from "../primitives/kdf";
|
||||||
import {
|
import { Timestamp, getTimestampNow } from "../../util/time";
|
||||||
Timestamp,
|
|
||||||
getTimestampNow,
|
|
||||||
timestampIsBetween,
|
|
||||||
} from "../../util/time";
|
|
||||||
|
|
||||||
enum SignaturePurpose {
|
enum SignaturePurpose {
|
||||||
RESERVE_WITHDRAW = 1200,
|
RESERVE_WITHDRAW = 1200,
|
||||||
@ -144,24 +134,9 @@ function buildSigPS(purposeNum: number): SignaturePurposeBuilder {
|
|||||||
return new SignaturePurposeBuilder(purposeNum);
|
return new SignaturePurposeBuilder(purposeNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkSignKeyOkay(
|
|
||||||
key: string,
|
|
||||||
exchangeKeys: ExchangeSignKeyJson[],
|
|
||||||
): boolean {
|
|
||||||
const now = getTimestampNow();
|
|
||||||
for (const k of exchangeKeys) {
|
|
||||||
if (k.key == key) {
|
|
||||||
return timestampIsBetween(now, k.stamp_start, k.stamp_end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CryptoImplementation {
|
export class CryptoImplementation {
|
||||||
static enableTracing = false;
|
static enableTracing = false;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a pre-coin of the given denomination to be withdrawn from then given
|
* Create a pre-coin of the given denomination to be withdrawn from then given
|
||||||
* reserve.
|
* reserve.
|
||||||
@ -535,7 +510,7 @@ export class CryptoImplementation {
|
|||||||
let time_eddsa_create = 0;
|
let time_eddsa_create = 0;
|
||||||
for (let i = 0; i < repetitions; i++) {
|
for (let i = 0; i < repetitions; i++) {
|
||||||
const start = timer.performanceNow();
|
const start = timer.performanceNow();
|
||||||
const pair = createEddsaKeyPair();
|
createEddsaKeyPair();
|
||||||
time_eddsa_create += timer.performanceNow() - start;
|
time_eddsa_create += timer.performanceNow() - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { CryptoWorkerFactory } from "./cryptoApi";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
(C) 2016 GNUnet e.V.
|
(C) 2016 GNUnet e.V.
|
||||||
@ -16,8 +14,10 @@ import { CryptoWorkerFactory } from "./cryptoApi";
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// tslint:disable:no-var-requires
|
/**
|
||||||
|
* Imports
|
||||||
|
*/
|
||||||
|
import { CryptoWorkerFactory } from "./cryptoApi";
|
||||||
import { CryptoWorker } from "./cryptoWorker";
|
import { CryptoWorker } from "./cryptoWorker";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import { CryptoImplementation } from "./cryptoImplementation";
|
import { CryptoImplementation } from "./cryptoImplementation";
|
||||||
@ -55,7 +55,7 @@ const workerCode = `
|
|||||||
* This function is executed in the worker thread to handle
|
* This function is executed in the worker thread to handle
|
||||||
* a message.
|
* a message.
|
||||||
*/
|
*/
|
||||||
export function handleWorkerMessage(msg: any) {
|
export function handleWorkerMessage(msg: any): void {
|
||||||
const args = msg.args;
|
const args = msg.args;
|
||||||
if (!Array.isArray(args)) {
|
if (!Array.isArray(args)) {
|
||||||
console.error("args must be array");
|
console.error("args must be array");
|
||||||
@ -72,7 +72,7 @@ export function handleWorkerMessage(msg: any) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRequest = async () => {
|
const handleRequest = async (): Promise<void> => {
|
||||||
const impl = new CryptoImplementation();
|
const impl = new CryptoImplementation();
|
||||||
|
|
||||||
if (!(operation in impl)) {
|
if (!(operation in impl)) {
|
||||||
@ -82,6 +82,7 @@ export function handleWorkerMessage(msg: any) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const result = (impl as any)[operation](...args);
|
const result = (impl as any)[operation](...args);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const worker_threads = require("worker_threads");
|
const worker_threads = require("worker_threads");
|
||||||
const p = worker_threads.parentPort;
|
const p = worker_threads.parentPort;
|
||||||
worker_threads.parentPort?.postMessage;
|
worker_threads.parentPort?.postMessage;
|
||||||
@ -101,7 +102,7 @@ export function handleWorkerMessage(msg: any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleWorkerError(e: Error) {
|
export function handleWorkerError(e: Error): void {
|
||||||
console.log("got error from worker", e);
|
console.log("got error from worker", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +136,7 @@ class NodeThreadCryptoWorker implements CryptoWorker {
|
|||||||
private nodeWorker: import("worker_threads").Worker;
|
private nodeWorker: import("worker_threads").Worker;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const worker_threads = require("worker_threads");
|
const worker_threads = require("worker_threads");
|
||||||
this.nodeWorker = new worker_threads.Worker(workerCode, { eval: true });
|
this.nodeWorker = new worker_threads.Worker(workerCode, { eval: true });
|
||||||
this.nodeWorker.on("error", (err: Error) => {
|
this.nodeWorker.on("error", (err: Error) => {
|
||||||
@ -168,14 +170,14 @@ class NodeThreadCryptoWorker implements CryptoWorker {
|
|||||||
/**
|
/**
|
||||||
* Send a message to the worker thread.
|
* Send a message to the worker thread.
|
||||||
*/
|
*/
|
||||||
postMessage(msg: any) {
|
postMessage(msg: any): void {
|
||||||
this.nodeWorker.postMessage(msg);
|
this.nodeWorker.postMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forcibly terminate the worker thread.
|
* Forcibly terminate the worker thread.
|
||||||
*/
|
*/
|
||||||
terminate() {
|
terminate(): void {
|
||||||
this.nodeWorker.terminate();
|
this.nodeWorker.terminate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,13 +70,17 @@ export class SynchronousCryptoWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private dispatchMessage(msg: any) {
|
private dispatchMessage(msg: any): void {
|
||||||
if (this.onmessage) {
|
if (this.onmessage) {
|
||||||
this.onmessage({ data: msg });
|
this.onmessage({ data: msg });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleRequest(operation: string, id: number, args: string[]) {
|
private async handleRequest(
|
||||||
|
operation: string,
|
||||||
|
id: number,
|
||||||
|
args: string[],
|
||||||
|
): Promise<void> {
|
||||||
const impl = new CryptoImplementation();
|
const impl = new CryptoImplementation();
|
||||||
|
|
||||||
if (!(operation in impl)) {
|
if (!(operation in impl)) {
|
||||||
@ -102,7 +106,7 @@ export class SynchronousCryptoWorker {
|
|||||||
/**
|
/**
|
||||||
* Send a message to the worker thread.
|
* Send a message to the worker thread.
|
||||||
*/
|
*/
|
||||||
postMessage(msg: any) {
|
postMessage(msg: any): void {
|
||||||
const args = msg.args;
|
const args = msg.args;
|
||||||
if (!Array.isArray(args)) {
|
if (!Array.isArray(args)) {
|
||||||
console.error("args must be array");
|
console.error("args must be array");
|
||||||
@ -127,7 +131,7 @@ export class SynchronousCryptoWorker {
|
|||||||
/**
|
/**
|
||||||
* Forcibly terminate the worker thread.
|
* Forcibly terminate the worker thread.
|
||||||
*/
|
*/
|
||||||
terminate() {
|
terminate(): void {
|
||||||
// This is a no-op.
|
// This is a no-op.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export function openTalerDatabase(
|
|||||||
db: IDBDatabase,
|
db: IDBDatabase,
|
||||||
oldVersion: number,
|
oldVersion: number,
|
||||||
newVersion: number,
|
newVersion: number,
|
||||||
) => {
|
): void => {
|
||||||
switch (oldVersion) {
|
switch (oldVersion) {
|
||||||
case 0: // DB does not exist yet
|
case 0: // DB does not exist yet
|
||||||
for (const n in Stores) {
|
for (const n in Stores) {
|
||||||
@ -53,6 +53,6 @@ export function openTalerDatabase(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteTalerDatabase(idbFactory: IDBFactory) {
|
export function deleteTalerDatabase(idbFactory: IDBFactory): void {
|
||||||
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
|
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ export class Bank {
|
|||||||
amount: string,
|
amount: string,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
exchangePaytoUri: string,
|
exchangePaytoUri: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
const reqUrl = new URL("testing/withdraw", this.bankBaseUrl).href;
|
const reqUrl = new URL("testing/withdraw", this.bankBaseUrl).href;
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
@ -117,7 +117,7 @@ export class CommandGroup<GN extends keyof any, TG> {
|
|||||||
private scArgs: SubcommandArgs,
|
private scArgs: SubcommandArgs,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
action(f: ActionFn<TG>) {
|
action(f: ActionFn<TG>): void {
|
||||||
if (this.myAction) {
|
if (this.myAction) {
|
||||||
throw Error("only one action supported per command");
|
throw Error("only one action supported per command");
|
||||||
}
|
}
|
||||||
@ -269,7 +269,7 @@ export class CommandGroup<GN extends keyof any, TG> {
|
|||||||
return cg as any;
|
return cg as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
printHelp(progName: string, parents: CommandGroup<any, any>[]) {
|
printHelp(progName: string, parents: CommandGroup<any, any>[]): void {
|
||||||
let usageSpec = "";
|
let usageSpec = "";
|
||||||
for (const p of parents) {
|
for (const p of parents) {
|
||||||
usageSpec += (p.name ?? progName) + " ";
|
usageSpec += (p.name ?? progName) + " ";
|
||||||
@ -320,7 +320,7 @@ export class CommandGroup<GN extends keyof any, TG> {
|
|||||||
parents: CommandGroup<any, any>[],
|
parents: CommandGroup<any, any>[],
|
||||||
unparsedArgs: string[],
|
unparsedArgs: string[],
|
||||||
parsedArgs: any,
|
parsedArgs: any,
|
||||||
) {
|
): void {
|
||||||
let posArgIndex = 0;
|
let posArgIndex = 0;
|
||||||
let argsTerminated = false;
|
let argsTerminated = false;
|
||||||
let i;
|
let i;
|
||||||
@ -507,7 +507,7 @@ export class Program<PN extends keyof any, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
run() {
|
run(): void {
|
||||||
const args = process.argv;
|
const args = process.argv;
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
console.error(
|
console.error(
|
||||||
|
@ -106,7 +106,7 @@ export async function getDefaultNodeWallet(
|
|||||||
myHttpLib = new NodeHttpLib();
|
myHttpLib = new NodeHttpLib();
|
||||||
}
|
}
|
||||||
|
|
||||||
const myVersionChange = () => {
|
const myVersionChange = (): Promise<void> => {
|
||||||
console.error("version change requested, should not happen");
|
console.error("version change requested, should not happen");
|
||||||
throw Error();
|
throw Error();
|
||||||
};
|
};
|
||||||
@ -141,7 +141,7 @@ export async function withdrawTestBalance(
|
|||||||
amount = "TESTKUDOS:10",
|
amount = "TESTKUDOS:10",
|
||||||
bankBaseUrl = "https://bank.test.taler.net/",
|
bankBaseUrl = "https://bank.test.taler.net/",
|
||||||
exchangeBaseUrl = "https://exchange.test.taler.net/",
|
exchangeBaseUrl = "https://exchange.test.taler.net/",
|
||||||
) {
|
): Promise<void> {
|
||||||
const reserveResponse = await myWallet.createReserve({
|
const reserveResponse = await myWallet.createReserve({
|
||||||
amount: amounts.parseOrThrow(amount),
|
amount: amounts.parseOrThrow(amount),
|
||||||
exchange: exchangeBaseUrl,
|
exchange: exchangeBaseUrl,
|
||||||
|
@ -65,7 +65,7 @@ export class MerchantBackendConnection {
|
|||||||
|
|
||||||
constructor(public merchantBaseUrl: string, public apiKey: string) {}
|
constructor(public merchantBaseUrl: string, public apiKey: string) {}
|
||||||
|
|
||||||
async authorizeTip(amount: string, justification: string) {
|
async authorizeTip(amount: string, justification: string): Promise<string> {
|
||||||
const reqUrl = new URL("tip-authorize", this.merchantBaseUrl).href;
|
const reqUrl = new URL("tip-authorize", this.merchantBaseUrl).href;
|
||||||
const tipReq = {
|
const tipReq = {
|
||||||
amount,
|
amount,
|
||||||
|
@ -22,7 +22,7 @@ import { runIntegrationTest, runIntegrationTestBasic } from "./integrationtest";
|
|||||||
import { Wallet } from "../wallet";
|
import { Wallet } from "../wallet";
|
||||||
import qrcodeGenerator from "qrcode-generator";
|
import qrcodeGenerator from "qrcode-generator";
|
||||||
import * as clk from "./clk";
|
import * as clk from "./clk";
|
||||||
import { BridgeIDBFactory, MemoryBackend } from "idb-bridge";
|
import { BridgeIDBFactory } from "idb-bridge";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { Amounts } from "../util/amounts";
|
import { Amounts } from "../util/amounts";
|
||||||
import { decodeCrock } from "../crypto/talerCrypto";
|
import { decodeCrock } from "../crypto/talerCrypto";
|
||||||
@ -46,7 +46,7 @@ async function doPay(
|
|||||||
wallet: Wallet,
|
wallet: Wallet,
|
||||||
payUrl: string,
|
payUrl: string,
|
||||||
options: { alwaysYes: boolean } = { alwaysYes: true },
|
options: { alwaysYes: boolean } = { alwaysYes: true },
|
||||||
) {
|
): Promise<void> {
|
||||||
const result = await wallet.preparePayForUri(payUrl);
|
const result = await wallet.preparePayForUri(payUrl);
|
||||||
if (result.status === "error") {
|
if (result.status === "error") {
|
||||||
console.error("Could not pay:", result.error);
|
console.error("Could not pay:", result.error);
|
||||||
@ -89,21 +89,22 @@ async function doPay(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pay) {
|
if (pay) {
|
||||||
const payRes = await wallet.confirmPay(result.proposalId, undefined);
|
await wallet.confirmPay(result.proposalId, undefined);
|
||||||
console.log("paid!");
|
console.log("paid!");
|
||||||
} else {
|
} else {
|
||||||
console.log("not paying");
|
console.log("not paying");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyVerbose(verbose: boolean) {
|
function applyVerbose(verbose: boolean): void {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
console.log("enabled verbose logging");
|
console.log("enabled verbose logging");
|
||||||
BridgeIDBFactory.enableTracing = true;
|
BridgeIDBFactory.enableTracing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function printVersion() {
|
function printVersion(): void {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const info = require("../../../package.json");
|
const info = require("../../../package.json");
|
||||||
console.log(`${info.version}`);
|
console.log(`${info.version}`);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
@ -329,7 +330,7 @@ exchangesCli
|
|||||||
.flag("force", ["-f", "--force"])
|
.flag("force", ["-f", "--force"])
|
||||||
.action(async (args) => {
|
.action(async (args) => {
|
||||||
await withWallet(args, async (wallet) => {
|
await withWallet(args, async (wallet) => {
|
||||||
const res = await wallet.updateExchangeFromUrl(
|
await wallet.updateExchangeFromUrl(
|
||||||
args.exchangesUpdateCmd.url,
|
args.exchangesUpdateCmd.url,
|
||||||
args.exchangesUpdateCmd.force,
|
args.exchangesUpdateCmd.force,
|
||||||
);
|
);
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes";
|
import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes";
|
||||||
import { Database, TransactionHandle } from "../util/query";
|
import { TransactionHandle } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
|
import { Stores, CoinStatus } from "../types/dbTypes";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
import { AmountJson } from "../util/amounts";
|
import { AmountJson } from "../util/amounts";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
|
@ -460,7 +460,8 @@ export async function updateExchangeFromUrl(
|
|||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<ExchangeRecord> {
|
): Promise<ExchangeRecord> {
|
||||||
const onOpErr = (e: OperationError): Promise<void> => setExchangeError(ws, baseUrl, e);
|
const onOpErr = (e: OperationError): Promise<void> =>
|
||||||
|
setExchangeError(ws, baseUrl, e);
|
||||||
return await guardOperationException(
|
return await guardOperationException(
|
||||||
() => updateExchangeFromUrlImpl(ws, baseUrl, forceNow),
|
() => updateExchangeFromUrlImpl(ws, baseUrl, forceNow),
|
||||||
onOpErr,
|
onOpErr,
|
||||||
|
@ -37,7 +37,7 @@ import {
|
|||||||
} from "../util/time";
|
} from "../util/time";
|
||||||
import { TransactionHandle } from "../util/query";
|
import { TransactionHandle } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { getBalances, getBalancesInsideTransaction } from "./balance";
|
import { getBalancesInsideTransaction } from "./balance";
|
||||||
import { ReserveType } from "../types/history";
|
import { ReserveType } from "../types/history";
|
||||||
|
|
||||||
function updateRetryDelay(
|
function updateRetryDelay(
|
||||||
@ -286,13 +286,23 @@ async function gatherProposalPending(
|
|||||||
if (onlyDue) {
|
if (onlyDue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const dl = proposal.download;
|
||||||
|
if (!dl) {
|
||||||
|
resp.pendingOperations.push({
|
||||||
|
type: PendingOperationType.Bug,
|
||||||
|
message: "proposal is in invalid state",
|
||||||
|
details: {},
|
||||||
|
givesLifeness: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: PendingOperationType.ProposalChoice,
|
type: PendingOperationType.ProposalChoice,
|
||||||
givesLifeness: false,
|
givesLifeness: false,
|
||||||
merchantBaseUrl: proposal.download!!.contractData.merchantBaseUrl,
|
merchantBaseUrl: dl.contractData.merchantBaseUrl,
|
||||||
proposalId: proposal.proposalId,
|
proposalId: proposal.proposalId,
|
||||||
proposalTimestamp: proposal.timestamp,
|
proposalTimestamp: proposal.timestamp,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else if (proposal.proposalStatus == ProposalStatus.DOWNLOADING) {
|
} else if (proposal.proposalStatus == ProposalStatus.DOWNLOADING) {
|
||||||
resp.nextRetryDelay = updateRetryDelay(
|
resp.nextRetryDelay = updateRetryDelay(
|
||||||
resp.nextRetryDelay,
|
resp.nextRetryDelay,
|
||||||
|
@ -279,7 +279,7 @@ async function recoupRefreshCoin(
|
|||||||
async function resetRecoupGroupRetry(
|
async function resetRecoupGroupRetry(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
recoupGroupId: string,
|
recoupGroupId: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
await ws.db.mutate(Stores.recoupGroups, recoupGroupId, (x) => {
|
await ws.db.mutate(Stores.recoupGroups, recoupGroupId, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
@ -294,7 +294,7 @@ export async function processRecoupGroup(
|
|||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await ws.memoProcessRecoup.memo(recoupGroupId, async () => {
|
await ws.memoProcessRecoup.memo(recoupGroupId, async () => {
|
||||||
const onOpErr = (e: OperationError) =>
|
const onOpErr = (e: OperationError): Promise<void> =>
|
||||||
incrementRecoupRetry(ws, recoupGroupId, e);
|
incrementRecoupRetry(ws, recoupGroupId, e);
|
||||||
return await guardOperationException(
|
return await guardOperationException(
|
||||||
async () => await processRecoupGroupImpl(ws, recoupGroupId, forceNow),
|
async () => await processRecoupGroupImpl(ws, recoupGroupId, forceNow),
|
||||||
|
@ -28,7 +28,7 @@ import {
|
|||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
} from "../types/dbTypes";
|
} from "../types/dbTypes";
|
||||||
import { amountToPretty } from "../util/helpers";
|
import { amountToPretty } from "../util/helpers";
|
||||||
import { Database, TransactionHandle } from "../util/query";
|
import { TransactionHandle } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { getWithdrawDenomList } from "./withdraw";
|
import { getWithdrawDenomList } from "./withdraw";
|
||||||
@ -390,8 +390,7 @@ async function refreshReveal(
|
|||||||
console.error("denom not found");
|
console.error("denom not found");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const pc =
|
const pc = refreshSession.planchetsForGammas[norevealIndex][i];
|
||||||
refreshSession.planchetsForGammas[refreshSession.norevealIndex!][i];
|
|
||||||
const denomSig = await ws.cryptoApi.rsaUnblind(
|
const denomSig = await ws.cryptoApi.rsaUnblind(
|
||||||
respJson.ev_sigs[i].ev_sig,
|
respJson.ev_sigs[i].ev_sig,
|
||||||
pc.blindingKey,
|
pc.blindingKey,
|
||||||
@ -485,7 +484,7 @@ export async function processRefreshGroup(
|
|||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await ws.memoProcessRefresh.memo(refreshGroupId, async () => {
|
await ws.memoProcessRefresh.memo(refreshGroupId, async () => {
|
||||||
const onOpErr = (e: OperationError) =>
|
const onOpErr = (e: OperationError): Promise<void> =>
|
||||||
incrementRefreshRetry(ws, refreshGroupId, e);
|
incrementRefreshRetry(ws, refreshGroupId, e);
|
||||||
return await guardOperationException(
|
return await guardOperationException(
|
||||||
async () => await processRefreshGroupImpl(ws, refreshGroupId, forceNow),
|
async () => await processRefreshGroupImpl(ws, refreshGroupId, forceNow),
|
||||||
@ -497,7 +496,7 @@ export async function processRefreshGroup(
|
|||||||
async function resetRefreshGroupRetry(
|
async function resetRefreshGroupRetry(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
await ws.db.mutate(Stores.refreshGroups, refreshSessionId, (x) => {
|
await ws.db.mutate(Stores.refreshGroups, refreshSessionId, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
@ -510,7 +509,7 @@ async function processRefreshGroupImpl(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshGroupId: string,
|
refreshGroupId: string,
|
||||||
forceNow: boolean,
|
forceNow: boolean,
|
||||||
) {
|
): Promise<void> {
|
||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetRefreshGroupRetry(ws, refreshGroupId);
|
await resetRefreshGroupRetry(ws, refreshGroupId);
|
||||||
}
|
}
|
||||||
@ -532,7 +531,7 @@ async function processRefreshSession(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshGroupId: string,
|
refreshGroupId: string,
|
||||||
coinIndex: number,
|
coinIndex: number,
|
||||||
) {
|
): Promise<void> {
|
||||||
logger.trace(
|
logger.trace(
|
||||||
`processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`,
|
`processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`,
|
||||||
);
|
);
|
||||||
|
@ -465,7 +465,7 @@ async function processPurchaseApplyRefundImpl(
|
|||||||
// Avoid duplicates
|
// Avoid duplicates
|
||||||
const refreshCoinsMap: { [coinPub: string]: CoinPublicKey } = {};
|
const refreshCoinsMap: { [coinPub: string]: CoinPublicKey } = {};
|
||||||
|
|
||||||
const modCoin = async (perm: MerchantRefundPermission) => {
|
const modCoin = async (perm: MerchantRefundPermission): Promise<void> => {
|
||||||
const c = await tx.get(Stores.coins, perm.coin_pub);
|
const c = await tx.get(Stores.coins, perm.coin_pub);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
console.warn("coin not found, can't apply refund");
|
console.warn("coin not found, can't apply refund");
|
||||||
|
@ -44,10 +44,7 @@ import {
|
|||||||
getExchangeTrust,
|
getExchangeTrust,
|
||||||
getExchangePaytoUri,
|
getExchangePaytoUri,
|
||||||
} from "./exchanges";
|
} from "./exchanges";
|
||||||
import {
|
import { codecForWithdrawOperationStatusResponse } from "../types/talerTypes";
|
||||||
WithdrawOperationStatusResponse,
|
|
||||||
codecForWithdrawOperationStatusResponse,
|
|
||||||
} from "../types/talerTypes";
|
|
||||||
import { assertUnreachable } from "../util/assertUnreachable";
|
import { assertUnreachable } from "../util/assertUnreachable";
|
||||||
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto";
|
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto";
|
||||||
import { randomBytes } from "../crypto/primitives/nacl-fast";
|
import { randomBytes } from "../crypto/primitives/nacl-fast";
|
||||||
@ -71,7 +68,10 @@ import {
|
|||||||
|
|
||||||
const logger = new Logger("reserves.ts");
|
const logger = new Logger("reserves.ts");
|
||||||
|
|
||||||
async function resetReserveRetry(ws: InternalWalletState, reservePub: string) {
|
async function resetReserveRetry(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
reservePub: string,
|
||||||
|
): Promise<void> {
|
||||||
await ws.db.mutate(Stores.reserves, reservePub, (x) => {
|
await ws.db.mutate(Stores.reserves, reservePub, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
@ -101,8 +101,6 @@ export async function createReserve(
|
|||||||
reserveStatus = ReserveRecordStatus.UNCONFIRMED;
|
reserveStatus = ReserveRecordStatus.UNCONFIRMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currency = req.amount.currency;
|
|
||||||
|
|
||||||
const reserveRecord: ReserveRecord = {
|
const reserveRecord: ReserveRecord = {
|
||||||
timestampCreated: now,
|
timestampCreated: now,
|
||||||
exchangeBaseUrl: canonExchange,
|
exchangeBaseUrl: canonExchange,
|
||||||
@ -251,7 +249,7 @@ export async function processReserve(
|
|||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return ws.memoProcessReserve.memo(reservePub, async () => {
|
return ws.memoProcessReserve.memo(reservePub, async () => {
|
||||||
const onOpError = (err: OperationError) =>
|
const onOpError = (err: OperationError): Promise<void> =>
|
||||||
incrementReserveRetry(ws, reservePub, err);
|
incrementReserveRetry(ws, reservePub, err);
|
||||||
await guardOperationException(
|
await guardOperationException(
|
||||||
() => processReserveImpl(ws, reservePub, forceNow),
|
() => processReserveImpl(ws, reservePub, forceNow),
|
||||||
@ -280,7 +278,8 @@ async function registerReserveWithBank(
|
|||||||
if (reserve.timestampReserveInfoPosted) {
|
if (reserve.timestampReserveInfoPosted) {
|
||||||
throw Error("bank claims that reserve info selection is not done");
|
throw Error("bank claims that reserve info selection is not done");
|
||||||
}
|
}
|
||||||
const bankResp = await ws.http.postJson(bankStatusUrl, {
|
// FIXME: parse bank response
|
||||||
|
await ws.http.postJson(bankStatusUrl, {
|
||||||
reserve_pub: reservePub,
|
reserve_pub: reservePub,
|
||||||
selected_exchange: reserve.exchangeWire,
|
selected_exchange: reserve.exchangeWire,
|
||||||
});
|
});
|
||||||
@ -305,7 +304,7 @@ export async function processReserveBankStatus(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const onOpError = (err: OperationError) =>
|
const onOpError = (err: OperationError): Promise<void> =>
|
||||||
incrementReserveRetry(ws, reservePub, err);
|
incrementReserveRetry(ws, reservePub, err);
|
||||||
await guardOperationException(
|
await guardOperationException(
|
||||||
() => processReserveBankStatusImpl(ws, reservePub),
|
() => processReserveBankStatusImpl(ws, reservePub),
|
||||||
@ -330,20 +329,13 @@ async function processReserveBankStatusImpl(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let status: WithdrawOperationStatusResponse;
|
|
||||||
try {
|
|
||||||
const statusResp = await ws.http.get(bankStatusUrl);
|
const statusResp = await ws.http.get(bankStatusUrl);
|
||||||
if (statusResp.status !== 200) {
|
if (statusResp.status !== 200) {
|
||||||
throw Error(
|
throw Error(`unexpected status ${statusResp.status} for bank status query`);
|
||||||
`unexpected status ${statusResp.status} for bank status query`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
status = codecForWithdrawOperationStatusResponse().decode(
|
const status = codecForWithdrawOperationStatusResponse().decode(
|
||||||
await statusResp.json(),
|
await statusResp.json(),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
ws.notify({ type: NotificationType.Wildcard });
|
ws.notify({ type: NotificationType.Wildcard });
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ export class InternalWalletState {
|
|||||||
this.cryptoApi = new CryptoApi(cryptoWorkerFactory);
|
this.cryptoApi = new CryptoApi(cryptoWorkerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public notify(n: WalletNotification) {
|
public notify(n: WalletNotification): void {
|
||||||
logger.trace("Notification", n);
|
logger.trace("Notification", n);
|
||||||
for (const l of this.listeners) {
|
for (const l of this.listeners) {
|
||||||
const nc = JSON.parse(JSON.stringify(n));
|
const nc = JSON.parse(JSON.stringify(n));
|
||||||
|
@ -18,9 +18,7 @@ import { InternalWalletState } from "./state";
|
|||||||
import { parseTipUri } from "../util/taleruri";
|
import { parseTipUri } from "../util/taleruri";
|
||||||
import { TipStatus, OperationError } from "../types/walletTypes";
|
import { TipStatus, OperationError } from "../types/walletTypes";
|
||||||
import {
|
import {
|
||||||
TipPickupGetResponse,
|
|
||||||
TipPlanchetDetail,
|
TipPlanchetDetail,
|
||||||
TipResponse,
|
|
||||||
codecForTipPickupGetResponse,
|
codecForTipPickupGetResponse,
|
||||||
codecForTipResponse,
|
codecForTipResponse,
|
||||||
} from "../types/talerTypes";
|
} from "../types/talerTypes";
|
||||||
@ -149,7 +147,8 @@ export async function processTip(
|
|||||||
tipId: string,
|
tipId: string,
|
||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const onOpErr = (e: OperationError) => incrementTipRetry(ws, tipId, e);
|
const onOpErr = (e: OperationError): Promise<void> =>
|
||||||
|
incrementTipRetry(ws, tipId, e);
|
||||||
await guardOperationException(
|
await guardOperationException(
|
||||||
() => processTipImpl(ws, tipId, forceNow),
|
() => processTipImpl(ws, tipId, forceNow),
|
||||||
onOpErr,
|
onOpErr,
|
||||||
@ -172,7 +171,7 @@ async function processTipImpl(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
tipId: string,
|
tipId: string,
|
||||||
forceNow: boolean,
|
forceNow: boolean,
|
||||||
) {
|
): Promise<void> {
|
||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetTipRetry(ws, tipId);
|
await resetTipRetry(ws, tipId);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import {
|
|||||||
DenominationStatus,
|
DenominationStatus,
|
||||||
CoinStatus,
|
CoinStatus,
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
PlanchetRecord,
|
|
||||||
initRetryInfo,
|
initRetryInfo,
|
||||||
updateRetryInfoTimeout,
|
updateRetryInfoTimeout,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
@ -52,14 +51,10 @@ import {
|
|||||||
timestampCmp,
|
timestampCmp,
|
||||||
timestampSubtractDuraction,
|
timestampSubtractDuraction,
|
||||||
} from "../util/time";
|
} from "../util/time";
|
||||||
import {
|
|
||||||
summarizeReserveHistory,
|
|
||||||
ReserveHistorySummary,
|
|
||||||
} from "../util/reserveHistoryUtil";
|
|
||||||
|
|
||||||
const logger = new Logger("withdraw.ts");
|
const logger = new Logger("withdraw.ts");
|
||||||
|
|
||||||
function isWithdrawableDenom(d: DenominationRecord) {
|
function isWithdrawableDenom(d: DenominationRecord): boolean {
|
||||||
const now = getTimestampNow();
|
const now = getTimestampNow();
|
||||||
const started = timestampCmp(now, d.stampStart) >= 0;
|
const started = timestampCmp(now, d.stampStart) >= 0;
|
||||||
const lastPossibleWithdraw = timestampSubtractDuraction(
|
const lastPossibleWithdraw = timestampSubtractDuraction(
|
||||||
@ -175,8 +170,6 @@ async function processPlanchet(
|
|||||||
if (withdrawalGroup.withdrawn[coinIdx]) {
|
if (withdrawalGroup.withdrawn[coinIdx]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (withdrawalGroup.source.type === "reserve") {
|
|
||||||
}
|
|
||||||
const planchet = withdrawalGroup.planchets[coinIdx];
|
const planchet = withdrawalGroup.planchets[coinIdx];
|
||||||
if (!planchet) {
|
if (!planchet) {
|
||||||
console.log("processPlanchet: planchet not found");
|
console.log("processPlanchet: planchet not found");
|
||||||
@ -248,7 +241,6 @@ async function processPlanchet(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let withdrawalGroupFinished = false;
|
let withdrawalGroupFinished = false;
|
||||||
let summary: ReserveHistorySummary | undefined = undefined;
|
|
||||||
|
|
||||||
const success = await ws.db.runWithWriteTransaction(
|
const success = await ws.db.runWithWriteTransaction(
|
||||||
[Stores.coins, Stores.withdrawalGroups, Stores.reserves],
|
[Stores.coins, Stores.withdrawalGroups, Stores.reserves],
|
||||||
@ -276,12 +268,6 @@ async function processPlanchet(
|
|||||||
withdrawalGroupFinished = true;
|
withdrawalGroupFinished = true;
|
||||||
}
|
}
|
||||||
await tx.put(Stores.withdrawalGroups, ws);
|
await tx.put(Stores.withdrawalGroups, ws);
|
||||||
if (!planchet.isFromTip) {
|
|
||||||
const r = await tx.get(Stores.reserves, planchet.reservePub);
|
|
||||||
if (r) {
|
|
||||||
summary = summarizeReserveHistory(r.reserveTransactions, r.currency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await tx.add(Stores.coins, coin);
|
await tx.add(Stores.coins, coin);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@ -396,7 +382,7 @@ export async function processWithdrawGroup(
|
|||||||
withdrawalGroupId: string,
|
withdrawalGroupId: string,
|
||||||
forceNow = false,
|
forceNow = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const onOpErr = (e: OperationError) =>
|
const onOpErr = (e: OperationError): Promise<void> =>
|
||||||
incrementWithdrawalRetry(ws, withdrawalGroupId, e);
|
incrementWithdrawalRetry(ws, withdrawalGroupId, e);
|
||||||
await guardOperationException(
|
await guardOperationException(
|
||||||
() => processWithdrawGroupImpl(ws, withdrawalGroupId, forceNow),
|
() => processWithdrawGroupImpl(ws, withdrawalGroupId, forceNow),
|
||||||
@ -407,7 +393,7 @@ export async function processWithdrawGroup(
|
|||||||
async function resetWithdrawalGroupRetry(
|
async function resetWithdrawalGroupRetry(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
withdrawalGroupId: string,
|
withdrawalGroupId: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
await ws.db.mutate(Stores.withdrawalGroups, withdrawalGroupId, (x) => {
|
await ws.db.mutate(Stores.withdrawalGroups, withdrawalGroupId, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
|
@ -179,20 +179,21 @@ export type ReserveTransaction =
|
|||||||
| ReserveClosingTransaction
|
| ReserveClosingTransaction
|
||||||
| ReserveRecoupTransaction;
|
| ReserveRecoupTransaction;
|
||||||
|
|
||||||
export const codecForReserveWithdrawTransaction = (): Codec<ReserveWithdrawTransaction> =>
|
export const codecForReserveWithdrawTransaction = (): Codec<
|
||||||
|
ReserveWithdrawTransaction
|
||||||
|
> =>
|
||||||
makeCodecForObject<ReserveWithdrawTransaction>()
|
makeCodecForObject<ReserveWithdrawTransaction>()
|
||||||
.property("amount", codecForString)
|
.property("amount", codecForString)
|
||||||
.property("h_coin_envelope", codecForString)
|
.property("h_coin_envelope", codecForString)
|
||||||
.property("h_denom_pub", codecForString)
|
.property("h_denom_pub", codecForString)
|
||||||
.property("reserve_sig", codecForString)
|
.property("reserve_sig", codecForString)
|
||||||
.property(
|
.property("type", makeCodecForConstString(ReserveTransactionType.Withdraw))
|
||||||
"type",
|
|
||||||
makeCodecForConstString(ReserveTransactionType.Withdraw),
|
|
||||||
)
|
|
||||||
.property("withdraw_fee", codecForString)
|
.property("withdraw_fee", codecForString)
|
||||||
.build("ReserveWithdrawTransaction");
|
.build("ReserveWithdrawTransaction");
|
||||||
|
|
||||||
export const codecForReserveCreditTransaction = (): Codec<ReserveCreditTransaction> =>
|
export const codecForReserveCreditTransaction = (): Codec<
|
||||||
|
ReserveCreditTransaction
|
||||||
|
> =>
|
||||||
makeCodecForObject<ReserveCreditTransaction>()
|
makeCodecForObject<ReserveCreditTransaction>()
|
||||||
.property("amount", codecForString)
|
.property("amount", codecForString)
|
||||||
.property("sender_account_url", codecForString)
|
.property("sender_account_url", codecForString)
|
||||||
@ -201,7 +202,9 @@ export const codecForReserveCreditTransaction = (): Codec<ReserveCreditTransacti
|
|||||||
.property("type", makeCodecForConstString(ReserveTransactionType.Credit))
|
.property("type", makeCodecForConstString(ReserveTransactionType.Credit))
|
||||||
.build("ReserveCreditTransaction");
|
.build("ReserveCreditTransaction");
|
||||||
|
|
||||||
export const codecForReserveClosingTransaction = (): Codec<ReserveClosingTransaction> =>
|
export const codecForReserveClosingTransaction = (): Codec<
|
||||||
|
ReserveClosingTransaction
|
||||||
|
> =>
|
||||||
makeCodecForObject<ReserveClosingTransaction>()
|
makeCodecForObject<ReserveClosingTransaction>()
|
||||||
.property("amount", codecForString)
|
.property("amount", codecForString)
|
||||||
.property("closing_fee", codecForString)
|
.property("closing_fee", codecForString)
|
||||||
@ -213,7 +216,9 @@ export const codecForReserveClosingTransaction = (): Codec<ReserveClosingTransac
|
|||||||
.property("wtid", codecForString)
|
.property("wtid", codecForString)
|
||||||
.build("ReserveClosingTransaction");
|
.build("ReserveClosingTransaction");
|
||||||
|
|
||||||
export const codecForReserveRecoupTransaction = (): Codec<ReserveRecoupTransaction> =>
|
export const codecForReserveRecoupTransaction = (): Codec<
|
||||||
|
ReserveRecoupTransaction
|
||||||
|
> =>
|
||||||
makeCodecForObject<ReserveRecoupTransaction>()
|
makeCodecForObject<ReserveRecoupTransaction>()
|
||||||
.property("amount", codecForString)
|
.property("amount", codecForString)
|
||||||
.property("coin_pub", codecForString)
|
.property("coin_pub", codecForString)
|
||||||
|
@ -43,7 +43,6 @@ import {
|
|||||||
ReserveRecoupTransaction,
|
ReserveRecoupTransaction,
|
||||||
} from "./ReserveTransaction";
|
} from "./ReserveTransaction";
|
||||||
import { Timestamp, Duration, getTimestampNow } from "../util/time";
|
import { Timestamp, Duration, getTimestampNow } from "../util/time";
|
||||||
import { Wallet } from "../wallet";
|
|
||||||
|
|
||||||
export enum ReserveRecordStatus {
|
export enum ReserveRecordStatus {
|
||||||
/**
|
/**
|
||||||
@ -1524,6 +1523,7 @@ export class WalletImportRecord {
|
|||||||
/**
|
/**
|
||||||
* The stores and indices for the wallet database.
|
* The stores and indices for the wallet database.
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace Stores {
|
export namespace Stores {
|
||||||
class ExchangesStore extends Store<ExchangeRecord> {
|
class ExchangesStore extends Store<ExchangeRecord> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { RefreshReason } from "./walletTypes";
|
import { RefreshReason } from "./walletTypes";
|
||||||
import { ReserveTransaction } from "./ReserveTransaction";
|
|
||||||
import { WithdrawalSource } from "./dbTypes";
|
import { WithdrawalSource } from "./dbTypes";
|
||||||
import { Timestamp } from "../util/time";
|
import { Timestamp } from "../util/time";
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import { OperationError } from "./walletTypes";
|
|
||||||
import { WithdrawCoinSource, WithdrawalSource } from "./dbTypes";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This file is part of GNU Taler
|
This file is part of GNU Taler
|
||||||
(C) 2019 GNUnet e.V.
|
(C) 2019 GNUnet e.V.
|
||||||
@ -22,6 +19,12 @@ import { WithdrawCoinSource, WithdrawalSource } from "./dbTypes";
|
|||||||
* of the wallet.
|
* of the wallet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import { OperationError } from "./walletTypes";
|
||||||
|
import { WithdrawalSource } from "./dbTypes";
|
||||||
|
|
||||||
export const enum NotificationType {
|
export const enum NotificationType {
|
||||||
CoinWithdrawn = "coin-withdrawn",
|
CoinWithdrawn = "coin-withdrawn",
|
||||||
ProposalAccepted = "proposal-accepted",
|
ProposalAccepted = "proposal-accepted",
|
||||||
|
@ -25,7 +25,6 @@ import { OperationError, WalletBalance } from "./walletTypes";
|
|||||||
import { WithdrawalSource, RetryInfo, ReserveRecordStatus } from "./dbTypes";
|
import { WithdrawalSource, RetryInfo, ReserveRecordStatus } from "./dbTypes";
|
||||||
import { Timestamp, Duration } from "../util/time";
|
import { Timestamp, Duration } from "../util/time";
|
||||||
import { ReserveType } from "./history";
|
import { ReserveType } from "./history";
|
||||||
import { AmountString } from "./talerTypes";
|
|
||||||
|
|
||||||
export const enum PendingOperationType {
|
export const enum PendingOperationType {
|
||||||
Bug = "bug",
|
Bug = "bug",
|
||||||
|
@ -21,12 +21,7 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import {
|
import { getTimestampNow, timestampDifference } from "../util/time";
|
||||||
getTimestampNow,
|
|
||||||
Timestamp,
|
|
||||||
timestampSubtractDuraction,
|
|
||||||
timestampDifference,
|
|
||||||
} from "../util/time";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum request per second, per origin.
|
* Maximum request per second, per origin.
|
||||||
|
@ -39,7 +39,7 @@ export function amountToPretty(amount: AmountJson): string {
|
|||||||
*
|
*
|
||||||
* See http://api.taler.net/wallet.html#general
|
* See http://api.taler.net/wallet.html#general
|
||||||
*/
|
*/
|
||||||
export function canonicalizeBaseUrl(url: string) {
|
export function canonicalizeBaseUrl(url: string): string {
|
||||||
if (!url.startsWith("http") && !url.startsWith("https")) {
|
if (!url.startsWith("http") && !url.startsWith("https")) {
|
||||||
url = "https://" + url;
|
url = "https://" + url;
|
||||||
}
|
}
|
||||||
@ -145,13 +145,3 @@ export function strcmp(s1: string, s2: string): number {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Run a function and return its result.
|
|
||||||
*
|
|
||||||
* Used as a nicer-looking way to do immediately invoked function
|
|
||||||
* expressions (IFFEs).
|
|
||||||
*/
|
|
||||||
export function runBlock<T>(f: () => T) {
|
|
||||||
return f();
|
|
||||||
}
|
|
||||||
|
@ -136,9 +136,13 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
const headerMap = new Headers();
|
const headerMap = new Headers();
|
||||||
arr.forEach(function (line) {
|
arr.forEach(function (line) {
|
||||||
const parts = line.split(": ");
|
const parts = line.split(": ");
|
||||||
const header = parts.shift();
|
const headerName = parts.shift();
|
||||||
|
if (!headerName) {
|
||||||
|
console.error("invalid header");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const value = parts.join(": ");
|
const value = parts.join(": ");
|
||||||
headerMap.set(header!, value);
|
headerMap.set(headerName, value);
|
||||||
});
|
});
|
||||||
const resp: HttpResponse = {
|
const resp: HttpResponse = {
|
||||||
status: myRequest.status,
|
status: myRequest.status,
|
||||||
@ -156,7 +160,11 @@ export class BrowserHttpLib implements HttpRequestLibrary {
|
|||||||
return this.req("get", url, undefined, opt);
|
return this.req("get", url, undefined, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
postJson(url: string, body: any, opt?: HttpRequestOptions): Promise<HttpResponse> {
|
postJson(
|
||||||
|
url: string,
|
||||||
|
body: any,
|
||||||
|
opt?: HttpRequestOptions,
|
||||||
|
): Promise<HttpResponse> {
|
||||||
return this.req("post", url, JSON.stringify(body), opt);
|
return this.req("post", url, JSON.stringify(body), opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,11 @@ export class TransactionHandle {
|
|||||||
return requestToPromise(req);
|
return requestToPromise(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutate<T>(store: Store<T>, key: any, f: (x: T) => T | undefined): Promise<void> {
|
mutate<T>(
|
||||||
|
store: Store<T>,
|
||||||
|
key: any,
|
||||||
|
f: (x: T) => T | undefined,
|
||||||
|
): Promise<void> {
|
||||||
const req = this.tx.objectStore(store.name).openCursor(key);
|
const req = this.tx.objectStore(store.name).openCursor(key);
|
||||||
return applyMutation(req, f);
|
return applyMutation(req, f);
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,6 @@ export class ConfigValue<T> {
|
|||||||
export class Configuration {
|
export class Configuration {
|
||||||
private sectionMap: SectionMap = {};
|
private sectionMap: SectionMap = {};
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
loadFromString(s: string): void {
|
loadFromString(s: string): void {
|
||||||
const reComment = /^\s*#.*$/;
|
const reComment = /^\s*#.*$/;
|
||||||
const reSection = /^\s*\[\s*([^\]]*)\s*\]\s*$/;
|
const reSection = /^\s*\[\s*([^\]]*)\s*\]\s*$/;
|
||||||
|
@ -28,7 +28,7 @@ test("taler pay url parsing: wrong scheme", (t) => {
|
|||||||
t.is(r1, undefined);
|
t.is(r1, undefined);
|
||||||
|
|
||||||
const url2 = "taler://refund/a/b/c/d/e/f";
|
const url2 = "taler://refund/a/b/c/d/e/f";
|
||||||
const r2 = parsePayUri(url1);
|
const r2 = parsePayUri(url2);
|
||||||
t.is(r2, undefined);
|
t.is(r2, undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ export function classifyTalerUri(s: string): TalerUriType {
|
|||||||
return TalerUriType.Unknown;
|
return TalerUriType.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOrderDownloadUrl(merchantBaseUrl: string, orderId: string) {
|
export function getOrderDownloadUrl(merchantBaseUrl: string, orderId: string): string {
|
||||||
const u = new URL("proposal", merchantBaseUrl);
|
const u = new URL("proposal", merchantBaseUrl);
|
||||||
u.searchParams.set("order_id", orderId);
|
u.searchParams.set("order_id", orderId);
|
||||||
return u.href;
|
return u.href;
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
*/
|
*/
|
||||||
import { Duration } from "./time";
|
import { Duration } from "./time";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancelable timer.
|
* Cancelable timer.
|
||||||
*/
|
*/
|
||||||
|
@ -154,7 +154,10 @@ export class Wallet {
|
|||||||
this.ws = new InternalWalletState(db, http, cryptoWorkerFactory);
|
this.ws = new InternalWalletState(db, http, cryptoWorkerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
getExchangePaytoUri(exchangeBaseUrl: string, supportedTargetTypes: string[]): Promise<string> {
|
getExchangePaytoUri(
|
||||||
|
exchangeBaseUrl: string,
|
||||||
|
supportedTargetTypes: string[],
|
||||||
|
): Promise<string> {
|
||||||
return getExchangePaytoUri(this.ws, exchangeBaseUrl, supportedTargetTypes);
|
return getExchangePaytoUri(this.ws, exchangeBaseUrl, supportedTargetTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,6 @@ export function isFirefox(): boolean {
|
|||||||
/**
|
/**
|
||||||
* Check if we are running under nodejs.
|
* Check if we are running under nodejs.
|
||||||
*/
|
*/
|
||||||
export function isNode() {
|
export function isNode(): boolean {
|
||||||
return typeof process !== "undefined" && process.release.name === "node";
|
return typeof process !== "undefined" && process.release.name === "node";
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ function setupJed(): any {
|
|||||||
/**
|
/**
|
||||||
* Convert template strings to a msgid
|
* Convert template strings to a msgid
|
||||||
*/
|
*/
|
||||||
function toI18nString(stringSeq: ReadonlyArray<string>) {
|
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
||||||
let s = "";
|
let s = "";
|
||||||
for (let i = 0; i < stringSeq.length; i++) {
|
for (let i = 0; i < stringSeq.length; i++) {
|
||||||
s += stringSeq[i];
|
s += stringSeq[i];
|
||||||
@ -71,7 +71,7 @@ function toI18nString(stringSeq: ReadonlyArray<string>) {
|
|||||||
/**
|
/**
|
||||||
* Internationalize a string template with arbitrary serialized values.
|
* Internationalize a string template with arbitrary serialized values.
|
||||||
*/
|
*/
|
||||||
export function str(stringSeq: TemplateStringsArray, ...values: any[]) {
|
export function str(stringSeq: TemplateStringsArray, ...values: any[]): string {
|
||||||
const s = toI18nString(stringSeq);
|
const s = toI18nString(stringSeq);
|
||||||
const tr = jed
|
const tr = jed
|
||||||
.translate(s)
|
.translate(s)
|
||||||
@ -226,8 +226,8 @@ export class TranslatePlural extends React.Component<
|
|||||||
typeof childArray[i] === "string" &&
|
typeof childArray[i] === "string" &&
|
||||||
typeof childArray[i + 1] === "string"
|
typeof childArray[i + 1] === "string"
|
||||||
) {
|
) {
|
||||||
childArray[i + i] =
|
childArray[i + i] = ((childArray[i] as string) +
|
||||||
((childArray[i] as string) + childArray[i + 1]) as string;
|
childArray[i + 1]) as string;
|
||||||
childArray.splice(i, 1);
|
childArray.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,8 +267,8 @@ export class TranslateSingular extends React.Component<
|
|||||||
typeof childArray[i] === "string" &&
|
typeof childArray[i] === "string" &&
|
||||||
typeof childArray[i + 1] === "string"
|
typeof childArray[i + 1] === "string"
|
||||||
) {
|
) {
|
||||||
childArray[i + i] =
|
childArray[i + i] = ((childArray[i] as string) +
|
||||||
((childArray[i] as string) + childArray[i + 1]) as string;
|
childArray[i + 1]) as string;
|
||||||
childArray.splice(i, 1);
|
childArray.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
import { AmountJson } from "../util/amounts";
|
import { AmountJson } from "../util/amounts";
|
||||||
import * as dbTypes from "../types/dbTypes";
|
import * as dbTypes from "../types/dbTypes";
|
||||||
import * as talerTypes from "../types/talerTypes";
|
|
||||||
import * as walletTypes from "../types/walletTypes";
|
import * as walletTypes from "../types/walletTypes";
|
||||||
|
|
||||||
import { UpgradeResponse } from "./wxApi";
|
import { UpgradeResponse } from "./wxApi";
|
||||||
@ -172,22 +171,3 @@ export interface MessageMap {
|
|||||||
*/
|
*/
|
||||||
export type MessageType = keyof MessageMap;
|
export type MessageType = keyof MessageMap;
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a request whose details match the request type.
|
|
||||||
*/
|
|
||||||
export function makeRequest<T extends MessageType>(
|
|
||||||
type: T,
|
|
||||||
details: MessageMap[T]["request"],
|
|
||||||
) {
|
|
||||||
return { type, details };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a response that matches the request type.
|
|
||||||
*/
|
|
||||||
export function makeResponse<T extends MessageType>(
|
|
||||||
type: T,
|
|
||||||
response: MessageMap[T]["response"],
|
|
||||||
) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
@ -25,7 +25,7 @@ import { createPopup } from "./pages/popup";
|
|||||||
import { createWithdrawPage } from "./pages/withdraw";
|
import { createWithdrawPage } from "./pages/withdraw";
|
||||||
import { createWelcomePage } from "./pages/welcome";
|
import { createWelcomePage } from "./pages/welcome";
|
||||||
|
|
||||||
function main() {
|
function main(): void {
|
||||||
try {
|
try {
|
||||||
let mainElement;
|
let mainElement;
|
||||||
const m = location.pathname.match(/([^/]+)$/);
|
const m = location.pathname.match(/([^/]+)$/);
|
||||||
|
@ -91,9 +91,7 @@ function ConfirmAuditor(props: ConfirmAuditorProps): JSX.Element {
|
|||||||
{addDone ? (
|
{addDone ? (
|
||||||
<div>
|
<div>
|
||||||
Auditor was added! You can also{" "}
|
Auditor was added! You can also{" "}
|
||||||
<a href={chrome.extension.getURL("/auditors.html")}>
|
<a href={chrome.extension.getURL("/auditors.html")}>view and edit</a>{" "}
|
||||||
view and edit
|
|
||||||
</a>{" "}
|
|
||||||
auditors.
|
auditors.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
import { getCurrencies, updateCurrency } from "../wxApi";
|
import { getCurrencies, updateCurrency } from "../wxApi";
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
|
|
||||||
interface CurrencyListState {
|
interface CurrencyListState {
|
||||||
currencies?: CurrencyRecord[];
|
currencies?: CurrencyRecord[];
|
||||||
@ -49,13 +48,16 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
this.state = {} as any;
|
this.state = {} as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
async update() {
|
async update(): Promise<void> {
|
||||||
const currencies = await getCurrencies();
|
const currencies = await getCurrencies();
|
||||||
console.log("currencies: ", currencies);
|
console.log("currencies: ", currencies);
|
||||||
this.setState({ currencies });
|
this.setState({ currencies });
|
||||||
}
|
}
|
||||||
|
|
||||||
async confirmRemoveAuditor(c: CurrencyRecord, a: AuditorRecord) {
|
async confirmRemoveAuditor(
|
||||||
|
c: CurrencyRecord,
|
||||||
|
a: AuditorRecord,
|
||||||
|
): Promise<void> {
|
||||||
if (
|
if (
|
||||||
window.confirm(
|
window.confirm(
|
||||||
`Do you really want to remove auditor ${a.baseUrl} for currency ${c.name}?`,
|
`Do you really want to remove auditor ${a.baseUrl} for currency ${c.name}?`,
|
||||||
@ -66,7 +68,10 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async confirmRemoveExchange(c: CurrencyRecord, e: ExchangeForCurrencyRecord) {
|
async confirmRemoveExchange(
|
||||||
|
c: CurrencyRecord,
|
||||||
|
e: ExchangeForCurrencyRecord,
|
||||||
|
): Promise<void> {
|
||||||
if (
|
if (
|
||||||
window.confirm(
|
window.confirm(
|
||||||
`Do you really want to remove exchange ${e.baseUrl} for currency ${c.name}?`,
|
`Do you really want to remove exchange ${e.baseUrl} for currency ${c.name}?`,
|
||||||
@ -86,7 +91,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
<p>Trusted Auditors:</p>
|
<p>Trusted Auditors:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{c.auditors.map((a) => (
|
{c.auditors.map((a) => (
|
||||||
<li>
|
<li key={a.baseUrl}>
|
||||||
{a.baseUrl}{" "}
|
{a.baseUrl}{" "}
|
||||||
<button
|
<button
|
||||||
className="pure-button button-destructive"
|
className="pure-button button-destructive"
|
||||||
@ -114,7 +119,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
<p>Trusted Exchanges:</p>
|
<p>Trusted Exchanges:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{c.exchanges.map((e) => (
|
{c.exchanges.map((e) => (
|
||||||
<li>
|
<li key={e.baseUrl}>
|
||||||
{e.baseUrl}{" "}
|
{e.baseUrl}{" "}
|
||||||
<button
|
<button
|
||||||
className="pure-button button-destructive"
|
className="pure-button button-destructive"
|
||||||
@ -137,7 +142,7 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
return (
|
return (
|
||||||
<div id="main">
|
<div id="main">
|
||||||
{currencies.map((c) => (
|
{currencies.map((c) => (
|
||||||
<div>
|
<div key={c.name}>
|
||||||
<h1>Currency {c.name}</h1>
|
<h1>Currency {c.name}</h1>
|
||||||
<p>Displayed with {c.fractionalDigits} fractional digits.</p>
|
<p>Displayed with {c.fractionalDigits} fractional digits.</p>
|
||||||
<h2>Auditors</h2>
|
<h2>Auditors</h2>
|
||||||
@ -151,6 +156,6 @@ class CurrencyList extends React.Component<{}, CurrencyListState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeAuditorsPage() {
|
export function makeAuditorsPage(): JSX.Element {
|
||||||
return <CurrencyList />;
|
return <CurrencyList />;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
setPayStatus(p);
|
setPayStatus(p);
|
||||||
};
|
};
|
||||||
doFetch();
|
doFetch();
|
||||||
}, [numTries]);
|
}, [numTries, talerPayUri]);
|
||||||
|
|
||||||
if (!payStatus) {
|
if (!payStatus) {
|
||||||
return <span>Loading payment information ...</span>;
|
return <span>Loading payment information ...</span>;
|
||||||
|
@ -25,6 +25,6 @@
|
|||||||
*/
|
*/
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export function makePaybackPage() {
|
export function makePaybackPage(): JSX.Element {
|
||||||
return <div>not implemented</div>;
|
return <div>not implemented</div>;
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,7 @@ import * as Amounts from "../../util/amounts";
|
|||||||
|
|
||||||
import { WalletBalance, WalletBalanceEntry } from "../../types/walletTypes";
|
import { WalletBalance, WalletBalanceEntry } from "../../types/walletTypes";
|
||||||
|
|
||||||
import {
|
import { abbrev, renderAmount, PageLink } from "../renderHtml";
|
||||||
abbrev,
|
|
||||||
renderAmount,
|
|
||||||
PageLink,
|
|
||||||
} from "../renderHtml";
|
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
import React, { Fragment } from "react";
|
import React, { Fragment } from "react";
|
||||||
@ -671,7 +667,7 @@ class WalletHistory extends React.Component<any, any> {
|
|||||||
console.log("rendering history");
|
console.log("rendering history");
|
||||||
const history: HistoryEvent[] = this.myHistory;
|
const history: HistoryEvent[] = this.myHistory;
|
||||||
if (this.gotError) {
|
if (this.gotError) {
|
||||||
return i18n.str`Error: could not retrieve event history`;
|
return <span>i18n.str`Error: could not retrieve event history`</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!history) {
|
if (!history) {
|
||||||
@ -734,18 +730,10 @@ function WalletDebug(props: any): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Debug tools:</p>
|
<p>Debug tools:</p>
|
||||||
<button onClick={openExtensionPage("/popup.html")}>
|
<button onClick={openExtensionPage("/popup.html")}>wallet tab</button>
|
||||||
wallet tab
|
<button onClick={openExtensionPage("/benchmark.html")}>benchmark</button>
|
||||||
</button>
|
<button onClick={openExtensionPage("/show-db.html")}>show db</button>
|
||||||
<button onClick={openExtensionPage("/benchmark.html")}>
|
<button onClick={openExtensionPage("/tree.html")}>show tree</button>
|
||||||
benchmark
|
|
||||||
</button>
|
|
||||||
<button onClick={openExtensionPage("/show-db.html")}>
|
|
||||||
show db
|
|
||||||
</button>
|
|
||||||
<button onClick={openExtensionPage("/tree.html")}>
|
|
||||||
show tree
|
|
||||||
</button>
|
|
||||||
<br />
|
<br />
|
||||||
<button onClick={confirmReset}>reset</button>
|
<button onClick={confirmReset}>reset</button>
|
||||||
<button onClick={reload}>reload chrome extension</button>
|
<button onClick={reload}>reload chrome extension</button>
|
||||||
|
@ -47,7 +47,7 @@ function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
doFetch();
|
doFetch();
|
||||||
}, []);
|
}, [props.talerRefundUri]);
|
||||||
|
|
||||||
console.log("rendering");
|
console.log("rendering");
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
|||||||
<>
|
<>
|
||||||
<h2>Refund Status</h2>
|
<h2>Refund Status</h2>
|
||||||
<p>
|
<p>
|
||||||
The product <em>{purchaseDetails.contractTerms.summary!}</em> has
|
The product <em>{purchaseDetails.contractTerms.summary}</em> has
|
||||||
received a total refund of{" "}
|
received a total refund of{" "}
|
||||||
<AmountView amount={purchaseDetails.totalRefundAmount} />.
|
<AmountView amount={purchaseDetails.totalRefundAmount} />.
|
||||||
</p>
|
</p>
|
||||||
@ -77,7 +77,7 @@ export function createRefundPage(): JSX.Element {
|
|||||||
|
|
||||||
const container = document.getElementById("container");
|
const container = document.getElementById("container");
|
||||||
if (!container) {
|
if (!container) {
|
||||||
throw Error("fatal: can't mount component, container missing")
|
throw Error("fatal: can't mount component, container missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
const talerRefundUri = url.searchParams.get("talerRefundUri");
|
const talerRefundUri = url.searchParams.get("talerRefundUri");
|
||||||
|
@ -42,17 +42,17 @@ class ResetNotification extends React.Component<any, State> {
|
|||||||
this.state = { checked: false, resetRequired: true };
|
this.state = { checked: false, resetRequired: true };
|
||||||
setInterval(() => this.update(), 500);
|
setInterval(() => this.update(), 500);
|
||||||
}
|
}
|
||||||
async update() {
|
async update(): Promise<void> {
|
||||||
const res = await wxApi.checkUpgrade();
|
const res = await wxApi.checkUpgrade();
|
||||||
this.setState({ resetRequired: res.dbResetRequired });
|
this.setState({ resetRequired: res.dbResetRequired });
|
||||||
}
|
}
|
||||||
render() {
|
render(): JSX.Element {
|
||||||
if (this.state.resetRequired) {
|
if (this.state.resetRequired) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Manual Reset Reqired</h1>
|
<h1>Manual Reset Reqired</h1>
|
||||||
<p>
|
<p>
|
||||||
The wallet's database in your browser is incompatible with the{" "}
|
The wallet's database in your browser is incompatible with the{" "}
|
||||||
currently installed wallet. Please reset manually.
|
currently installed wallet. Please reset manually.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -88,6 +88,6 @@ class ResetNotification extends React.Component<any, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createResetRequiredPage() {
|
export function createResetRequiredPage(): JSX.Element {
|
||||||
return <ResetNotification />;
|
return <ResetNotification />;
|
||||||
}
|
}
|
||||||
|
@ -290,8 +290,9 @@ class ReturnCoins extends React.Component<{}, ReturnCoinsState> {
|
|||||||
<div id="main">
|
<div id="main">
|
||||||
<h1>Wire electronic cash back to own bank account</h1>
|
<h1>Wire electronic cash back to own bank account</h1>
|
||||||
<p>
|
<p>
|
||||||
You can send coins back into your own bank account. Note that you're
|
You can send coins back into your own bank account. Note that
|
||||||
acting as a merchant when doing this, and thus the same fees apply.
|
you're acting as a merchant when doing this, and thus the same
|
||||||
|
fees apply.
|
||||||
</p>
|
</p>
|
||||||
{this.state.lastConfirmedDetail ? (
|
{this.state.lastConfirmedDetail ? (
|
||||||
<p className="okaybox">
|
<p className="okaybox">
|
||||||
|
@ -25,10 +25,7 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { acceptTip, getTipStatus } from "../wxApi";
|
import { acceptTip, getTipStatus } from "../wxApi";
|
||||||
|
|
||||||
import {
|
import { renderAmount, ProgressButton } from "../renderHtml";
|
||||||
renderAmount,
|
|
||||||
ProgressButton,
|
|
||||||
} from "../renderHtml";
|
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { TipStatus } from "../../types/walletTypes";
|
import { TipStatus } from "../../types/walletTypes";
|
||||||
@ -45,7 +42,7 @@ function TipDisplay(props: { talerTipUri: string }): JSX.Element {
|
|||||||
setTipStatus(ts);
|
setTipStatus(ts);
|
||||||
};
|
};
|
||||||
doFetch();
|
doFetch();
|
||||||
}, []);
|
}, [props.talerTipUri]);
|
||||||
|
|
||||||
if (discarded) {
|
if (discarded) {
|
||||||
return <span>You've discarded the tip.</span>;
|
return <span>You've discarded the tip.</span>;
|
||||||
|
@ -69,7 +69,7 @@ function Diagnostics(): JSX.Element {
|
|||||||
<p>Problems detected:</p>
|
<p>Problems detected:</p>
|
||||||
<ol>
|
<ol>
|
||||||
{diagnostics.errors.map((errMsg) => (
|
{diagnostics.errors.map((errMsg) => (
|
||||||
<li>{errMsg}</li>
|
<li key={errMsg}>{errMsg}</li>
|
||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
{diagnostics.firefoxIdbProblem ? (
|
{diagnostics.firefoxIdbProblem ? (
|
||||||
|
@ -30,7 +30,9 @@ import { WithdrawDetailView, renderAmount } from "../renderHtml";
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
|
import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
|
||||||
|
|
||||||
function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element {
|
function NewExchangeSelection(props: {
|
||||||
|
talerWithdrawUri: string;
|
||||||
|
}): JSX.Element {
|
||||||
const [details, setDetails] = useState<WithdrawDetails | undefined>();
|
const [details, setDetails] = useState<WithdrawDetails | undefined>();
|
||||||
const [selectedExchange, setSelectedExchange] = useState<
|
const [selectedExchange, setSelectedExchange] = useState<
|
||||||
string | undefined
|
string | undefined
|
||||||
@ -63,7 +65,7 @@ function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element
|
|||||||
setDetails(d);
|
setDetails(d);
|
||||||
};
|
};
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [selectedExchange, errMsg, selecting]);
|
}, [selectedExchange, errMsg, selecting, talerWithdrawUri]);
|
||||||
|
|
||||||
if (errMsg) {
|
if (errMsg) {
|
||||||
return (
|
return (
|
||||||
@ -145,8 +147,11 @@ function NewExchangeSelection(props: { talerWithdrawUri: string }): JSX.Element
|
|||||||
}
|
}
|
||||||
|
|
||||||
const accept = async (): Promise<void> => {
|
const accept = async (): Promise<void> => {
|
||||||
|
if (!selectedExchange) {
|
||||||
|
throw Error("can't accept, no exchange selected");
|
||||||
|
}
|
||||||
console.log("accepting exchange", selectedExchange);
|
console.log("accepting exchange", selectedExchange);
|
||||||
const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange!);
|
const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange);
|
||||||
console.log("accept withdrawal response", res);
|
console.log("accept withdrawal response", res);
|
||||||
if (res.confirmTransferUrl) {
|
if (res.confirmTransferUrl) {
|
||||||
document.location.href = res.confirmTransferUrl;
|
document.location.href = res.confirmTransferUrl;
|
||||||
|
@ -127,6 +127,37 @@ export class Collapsible extends React.Component<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function WireFee(props: {
|
||||||
|
s: string;
|
||||||
|
rci: ExchangeWithdrawDetails;
|
||||||
|
}): JSX.Element {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colSpan={3}>Wire Method {props.s}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Applies Until</th>
|
||||||
|
<th>Wire Fee</th>
|
||||||
|
<th>Closing Fee</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
,
|
||||||
|
<tbody>
|
||||||
|
{props.rci.wireFees.feesForType[props.s].map((f) => (
|
||||||
|
<tr key={f.sig}>
|
||||||
|
<td>{stringifyTimestamp(f.endStamp)}</td>
|
||||||
|
<td>{renderAmount(f.wireFee)}</td>
|
||||||
|
<td>{renderAmount(f.closingFee)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
,
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function AuditorDetailsView(props: {
|
function AuditorDetailsView(props: {
|
||||||
rci: ExchangeWithdrawDetails | null;
|
rci: ExchangeWithdrawDetails | null;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
@ -145,7 +176,7 @@ function AuditorDetailsView(props: {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{(rci.exchangeInfo.details?.auditors ?? []).map((a) => (
|
{(rci.exchangeInfo.details?.auditors ?? []).map((a) => (
|
||||||
<div>
|
<div key={a.auditor_pub}>
|
||||||
<h3>Auditor {a.auditor_url}</h3>
|
<h3>Auditor {a.auditor_url}</h3>
|
||||||
<p>
|
<p>
|
||||||
Public key: <ExpanderText text={a.auditor_pub} />
|
Public key: <ExpanderText text={a.auditor_pub} />
|
||||||
@ -202,30 +233,6 @@ function FeeDetailsView(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function wireFee(s: string) {
|
|
||||||
return [
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colSpan={3}>Wire Method {s}</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Applies Until</th>
|
|
||||||
<th>Wire Fee</th>
|
|
||||||
<th>Closing Fee</th>
|
|
||||||
</tr>
|
|
||||||
</thead>,
|
|
||||||
<tbody>
|
|
||||||
{rci!.wireFees.feesForType[s].map((f) => (
|
|
||||||
<tr>
|
|
||||||
<td>{stringifyTimestamp(f.endStamp)}</td>
|
|
||||||
<td>{renderAmount(f.wireFee)}</td>
|
|
||||||
<td>{renderAmount(f.closingFee)}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const withdrawFee = renderAmount(rci.withdrawFee);
|
const withdrawFee = renderAmount(rci.withdrawFee);
|
||||||
const overhead = renderAmount(rci.overhead);
|
const overhead = renderAmount(rci.overhead);
|
||||||
|
|
||||||
@ -265,7 +272,9 @@ function FeeDetailsView(props: {
|
|||||||
<h3>Wire Fees</h3>
|
<h3>Wire Fees</h3>
|
||||||
<div style={{ overflow: "auto" }}>
|
<div style={{ overflow: "auto" }}>
|
||||||
<table className="pure-table">
|
<table className="pure-table">
|
||||||
{Object.keys(rci.wireFees.feesForType).map(wireFee)}
|
{Object.keys(rci.wireFees.feesForType).map((s) => (
|
||||||
|
<WireFee key={s} s={s} rci={rci} />
|
||||||
|
))}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -337,7 +346,12 @@ export function PageLink(
|
|||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const url = chrome.extension.getURL(`/${props.pageName}`);
|
const url = chrome.extension.getURL(`/${props.pageName}`);
|
||||||
return (
|
return (
|
||||||
<a className="actionLink" href={url} target="_blank" rel="noopener noreferrer">
|
<a
|
||||||
|
className="actionLink"
|
||||||
|
href={url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
116
yarn.lock
116
yarn.lock
@ -175,6 +175,13 @@
|
|||||||
core-js-pure "^3.0.0"
|
core-js-pure "^3.0.0"
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.4.5":
|
||||||
|
version "7.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06"
|
||||||
|
integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
"@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
||||||
version "7.8.6"
|
version "7.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
||||||
@ -411,6 +418,26 @@
|
|||||||
eslint-scope "^5.0.0"
|
eslint-scope "^5.0.0"
|
||||||
eslint-utils "^2.0.0"
|
eslint-utils "^2.0.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/experimental-utils@2.27.0":
|
||||||
|
version "2.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz#801a952c10b58e486c9a0b36cf21e2aab1e9e01a"
|
||||||
|
integrity sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw==
|
||||||
|
dependencies:
|
||||||
|
"@types/json-schema" "^7.0.3"
|
||||||
|
"@typescript-eslint/typescript-estree" "2.27.0"
|
||||||
|
eslint-scope "^5.0.0"
|
||||||
|
eslint-utils "^2.0.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/parser@^2.24.0":
|
||||||
|
version "2.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287"
|
||||||
|
integrity sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg==
|
||||||
|
dependencies:
|
||||||
|
"@types/eslint-visitor-keys" "^1.0.0"
|
||||||
|
"@typescript-eslint/experimental-utils" "2.27.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "2.27.0"
|
||||||
|
eslint-visitor-keys "^1.1.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^2.26.0":
|
"@typescript-eslint/parser@^2.26.0":
|
||||||
version "2.26.0"
|
version "2.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.26.0.tgz#385463615818b33acb72a25b39c03579df93d76f"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.26.0.tgz#385463615818b33acb72a25b39c03579df93d76f"
|
||||||
@ -434,6 +461,19 @@
|
|||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
tsutils "^3.17.1"
|
tsutils "^3.17.1"
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree@2.27.0":
|
||||||
|
version "2.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8"
|
||||||
|
integrity sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.1"
|
||||||
|
eslint-visitor-keys "^1.1.0"
|
||||||
|
glob "^7.1.6"
|
||||||
|
is-glob "^4.0.1"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
semver "^6.3.0"
|
||||||
|
tsutils "^3.17.1"
|
||||||
|
|
||||||
acorn-jsx@^5.2.0:
|
acorn-jsx@^5.2.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
|
||||||
@ -546,6 +586,14 @@ argparse@^1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sprintf-js "~1.0.2"
|
sprintf-js "~1.0.2"
|
||||||
|
|
||||||
|
aria-query@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
|
||||||
|
integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
|
||||||
|
dependencies:
|
||||||
|
ast-types-flow "0.0.7"
|
||||||
|
commander "^2.11.0"
|
||||||
|
|
||||||
array-find-index@^1.0.1:
|
array-find-index@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
||||||
@ -588,6 +636,11 @@ arrify@^2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
|
resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
|
||||||
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
|
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
|
||||||
|
|
||||||
|
ast-types-flow@0.0.7, ast-types-flow@^0.0.7:
|
||||||
|
version "0.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
|
||||||
|
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
|
||||||
|
|
||||||
astral-regex@^1.0.0:
|
astral-regex@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
|
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
|
||||||
@ -663,6 +716,11 @@ axios@^0.19.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "1.5.10"
|
follow-redirects "1.5.10"
|
||||||
|
|
||||||
|
axobject-query@^2.0.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.2.tgz#2bdffc0371e643e5f03ba99065d5179b9ca79799"
|
||||||
|
integrity sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
@ -916,7 +974,7 @@ color-name@~1.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
commander@^2.20.0, commander@~2.20.3:
|
commander@^2.11.0, commander@^2.20.0, commander@~2.20.3:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
@ -965,6 +1023,11 @@ configstore@^5.0.1:
|
|||||||
write-file-atomic "^3.0.0"
|
write-file-atomic "^3.0.0"
|
||||||
xdg-basedir "^4.0.0"
|
xdg-basedir "^4.0.0"
|
||||||
|
|
||||||
|
confusing-browser-globals@^1.0.9:
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
|
||||||
|
integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==
|
||||||
|
|
||||||
contains-path@^0.1.0:
|
contains-path@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
|
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
|
||||||
@ -1024,6 +1087,11 @@ currently-unhandled@^0.4.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
array-find-index "^1.0.1"
|
array-find-index "^1.0.1"
|
||||||
|
|
||||||
|
damerau-levenshtein@^1.0.4:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791"
|
||||||
|
integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==
|
||||||
|
|
||||||
date-time@^2.1.0:
|
date-time@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2"
|
resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2"
|
||||||
@ -1160,7 +1228,7 @@ emittery@^0.6.0:
|
|||||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.6.0.tgz#e85312468d77c3ed9a6adf43bb57d34849e0c95a"
|
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.6.0.tgz#e85312468d77c3ed9a6adf43bb57d34849e0c95a"
|
||||||
integrity sha512-6EMRGr9KzYWp8DzHFZsKVZBsMO6QhAeHMeHND8rhyBNCHKMLpgW9tZv40bwN3rAIKRS5CxcK8oLRKUJSB9h7yQ==
|
integrity sha512-6EMRGr9KzYWp8DzHFZsKVZBsMO6QhAeHMeHND8rhyBNCHKMLpgW9tZv40bwN3rAIKRS5CxcK8oLRKUJSB9h7yQ==
|
||||||
|
|
||||||
emoji-regex@^7.0.1:
|
emoji-regex@^7.0.1, emoji-regex@^7.0.2:
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||||
@ -1242,6 +1310,33 @@ escape-string-regexp@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
||||||
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
||||||
|
|
||||||
|
eslint-config-airbnb-base@^14.1.0:
|
||||||
|
version "14.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.1.0.tgz#2ba4592dd6843258221d9bff2b6831bd77c874e4"
|
||||||
|
integrity sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw==
|
||||||
|
dependencies:
|
||||||
|
confusing-browser-globals "^1.0.9"
|
||||||
|
object.assign "^4.1.0"
|
||||||
|
object.entries "^1.1.1"
|
||||||
|
|
||||||
|
eslint-config-airbnb-typescript@^7.2.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-7.2.0.tgz#afa7cea5657c9f70c0b96d52bf7d470e9827b66a"
|
||||||
|
integrity sha512-W7IZUIJpBZIzU3p65KoyJPl2vGSy6FS3R+K91Cp3NLK/0m1oyvCFeBHI2QlWdqxkJ4FvwnLvsoRTutwpKNIT+A==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/parser" "^2.24.0"
|
||||||
|
eslint-config-airbnb "^18.1.0"
|
||||||
|
eslint-config-airbnb-base "^14.1.0"
|
||||||
|
|
||||||
|
eslint-config-airbnb@^18.1.0:
|
||||||
|
version "18.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.1.0.tgz#724d7e93dadd2169492ff5363c5aaa779e01257d"
|
||||||
|
integrity sha512-kZFuQC/MPnH7KJp6v95xsLBf63G/w7YqdPfQ0MUanxQ7zcKUNG8j+sSY860g3NwCBOa62apw16J6pRN+AOgXzw==
|
||||||
|
dependencies:
|
||||||
|
eslint-config-airbnb-base "^14.1.0"
|
||||||
|
object.assign "^4.1.0"
|
||||||
|
object.entries "^1.1.1"
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.3.2:
|
eslint-import-resolver-node@^0.3.2:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404"
|
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404"
|
||||||
@ -1276,6 +1371,21 @@ eslint-plugin-import@^2.20.2:
|
|||||||
read-pkg-up "^2.0.0"
|
read-pkg-up "^2.0.0"
|
||||||
resolve "^1.12.0"
|
resolve "^1.12.0"
|
||||||
|
|
||||||
|
eslint-plugin-jsx-a11y@^6.2.3:
|
||||||
|
version "6.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz#b872a09d5de51af70a97db1eea7dc933043708aa"
|
||||||
|
integrity sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.4.5"
|
||||||
|
aria-query "^3.0.0"
|
||||||
|
array-includes "^3.0.3"
|
||||||
|
ast-types-flow "^0.0.7"
|
||||||
|
axobject-query "^2.0.2"
|
||||||
|
damerau-levenshtein "^1.0.4"
|
||||||
|
emoji-regex "^7.0.2"
|
||||||
|
has "^1.0.3"
|
||||||
|
jsx-ast-utils "^2.2.1"
|
||||||
|
|
||||||
eslint-plugin-react-hooks@^3.0.0:
|
eslint-plugin-react-hooks@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz#9e80c71846eb68dd29c3b21d832728aa66e5bd35"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz#9e80c71846eb68dd29c3b21d832728aa66e5bd35"
|
||||||
@ -2217,7 +2327,7 @@ jsonfile@^4.0.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs "^4.1.6"
|
graceful-fs "^4.1.6"
|
||||||
|
|
||||||
jsx-ast-utils@^2.2.3:
|
jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f"
|
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f"
|
||||||
integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==
|
integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==
|
||||||
|
Loading…
Reference in New Issue
Block a user