cleanup, avoid some circular deps
This commit is contained in:
parent
35a7b76a7d
commit
c2ee8fd9ab
@ -22,12 +22,10 @@ import BridgeIDBRequest from "./BridgeIDBRequest";
|
|||||||
import compareKeys from "./util/cmp";
|
import compareKeys from "./util/cmp";
|
||||||
import {
|
import {
|
||||||
DataError,
|
DataError,
|
||||||
InvalidAccessError,
|
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
ReadOnlyError,
|
ReadOnlyError,
|
||||||
TransactionInactiveError,
|
TransactionInactiveError,
|
||||||
} from "./util/errors";
|
} from "./util/errors";
|
||||||
import extractKey from "./util/extractKey";
|
|
||||||
import structuredClone from "./util/structuredClone";
|
import structuredClone from "./util/structuredClone";
|
||||||
import {
|
import {
|
||||||
CursorRange,
|
CursorRange,
|
||||||
@ -41,7 +39,6 @@ import {
|
|||||||
RecordGetRequest,
|
RecordGetRequest,
|
||||||
ResultLevel,
|
ResultLevel,
|
||||||
Backend,
|
Backend,
|
||||||
DatabaseTransaction,
|
|
||||||
RecordStoreRequest,
|
RecordStoreRequest,
|
||||||
StoreLevel,
|
StoreLevel,
|
||||||
} from "./backend-interface";
|
} from "./backend-interface";
|
||||||
|
@ -24,16 +24,11 @@ import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
DataError,
|
|
||||||
InvalidAccessError,
|
InvalidAccessError,
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
NotFoundError,
|
|
||||||
ReadOnlyError,
|
ReadOnlyError,
|
||||||
TransactionInactiveError,
|
|
||||||
} from "./util/errors";
|
} from "./util/errors";
|
||||||
import extractKey from "./util/extractKey";
|
|
||||||
import fakeDOMStringList from "./util/fakeDOMStringList";
|
import fakeDOMStringList from "./util/fakeDOMStringList";
|
||||||
import structuredClone from "./util/structuredClone";
|
|
||||||
import {
|
import {
|
||||||
FakeDOMStringList,
|
FakeDOMStringList,
|
||||||
BridgeIDBCursorDirection,
|
BridgeIDBCursorDirection,
|
||||||
|
@ -4,28 +4,27 @@ import nodeResolve from 'rollup-plugin-node-resolve';
|
|||||||
import json from '@rollup/plugin-json';
|
import json from '@rollup/plugin-json';
|
||||||
import builtins from 'builtin-modules'
|
import builtins from 'builtin-modules'
|
||||||
|
|
||||||
|
|
||||||
const walletCli = {
|
const walletCli = {
|
||||||
input: 'dist/node/headless/taler-wallet-cli.js',
|
input: 'dist/node/headless/taler-wallet-cli.js',
|
||||||
output: {
|
output: {
|
||||||
file: 'dist/standalone/taler-wallet-cli.js',
|
file: 'dist/standalone/taler-wallet-cli.js',
|
||||||
format: 'cjs'
|
format: 'cjs'
|
||||||
},
|
},
|
||||||
|
external: builtins,
|
||||||
plugins: [
|
plugins: [
|
||||||
json(),
|
|
||||||
|
|
||||||
nodeResolve({
|
nodeResolve({
|
||||||
external: builtins,
|
preferBuiltins: true,
|
||||||
preferBuiltins: true
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
commonjs({
|
commonjs({
|
||||||
include: ['node_modules/**', 'dist/node/**'],
|
include: ['node_modules/**', 'dist/node/**'],
|
||||||
extensions: [ '.js' ],
|
extensions: [ '.js' ],
|
||||||
ignoreGlobal: false, // Default: false
|
ignoreGlobal: false, // Default: false
|
||||||
sourceMap: false,
|
sourceMap: false,
|
||||||
ignore: [ 'taler-wallet' ]
|
ignore: [ 'taler-wallet' ]
|
||||||
})
|
}),
|
||||||
|
|
||||||
|
json(),
|
||||||
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,11 +35,11 @@ const walletAndroid = {
|
|||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
exports: 'named',
|
exports: 'named',
|
||||||
},
|
},
|
||||||
|
external: builtins,
|
||||||
plugins: [
|
plugins: [
|
||||||
json(),
|
json(),
|
||||||
|
|
||||||
nodeResolve({
|
nodeResolve({
|
||||||
external: builtins,
|
|
||||||
preferBuiltins: true
|
preferBuiltins: true
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { WALLET_CACHE_BREAKER_CLIENT_VERSION } from "../wallet";
|
|
||||||
import { KeysJson, Denomination, ExchangeWireJson } from "../types/talerTypes";
|
import { KeysJson, Denomination, ExchangeWireJson } from "../types/talerTypes";
|
||||||
import { getTimestampNow, OperationError } from "../types/walletTypes";
|
import { getTimestampNow, OperationError } from "../types/walletTypes";
|
||||||
import {
|
import {
|
||||||
@ -40,6 +39,7 @@ import {
|
|||||||
OperationFailedAndReportedError,
|
OperationFailedAndReportedError,
|
||||||
guardOperationException,
|
guardOperationException,
|
||||||
} from "./errors";
|
} from "./errors";
|
||||||
|
import { WALLET_CACHE_BREAKER_CLIENT_VERSION } from "./versions";
|
||||||
|
|
||||||
async function denominationRecordFromKeys(
|
async function denominationRecordFromKeys(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
getTimestampNow,
|
getTimestampNow,
|
||||||
ConfirmReserveRequest,
|
ConfirmReserveRequest,
|
||||||
OperationError,
|
OperationError,
|
||||||
|
AcceptWithdrawalResponse,
|
||||||
} from "../types/walletTypes";
|
} from "../types/walletTypes";
|
||||||
import { canonicalizeBaseUrl } from "../util/helpers";
|
import { canonicalizeBaseUrl } from "../util/helpers";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
@ -38,7 +39,7 @@ import {
|
|||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
import { updateExchangeFromUrl, getExchangeTrust } from "./exchanges";
|
import { updateExchangeFromUrl, getExchangeTrust, getExchangePaytoUri } from "./exchanges";
|
||||||
import { WithdrawOperationStatusResponse } from "../types/talerTypes";
|
import { WithdrawOperationStatusResponse } 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";
|
||||||
@ -46,6 +47,7 @@ import { randomBytes } from "../crypto/primitives/nacl-fast";
|
|||||||
import {
|
import {
|
||||||
getVerifiedWithdrawDenomList,
|
getVerifiedWithdrawDenomList,
|
||||||
processWithdrawSession,
|
processWithdrawSession,
|
||||||
|
getBankWithdrawalInfo,
|
||||||
} from "./withdraw";
|
} from "./withdraw";
|
||||||
import { guardOperationException, OperationFailedAndReportedError } from "./errors";
|
import { guardOperationException, OperationFailedAndReportedError } from "./errors";
|
||||||
import { NotificationType } from "../types/notifications";
|
import { NotificationType } from "../types/notifications";
|
||||||
@ -652,3 +654,33 @@ async function depleteReserve(
|
|||||||
console.trace("withdraw session already existed");
|
console.trace("withdraw session already existed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function createTalerWithdrawReserve(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
talerWithdrawUri: string,
|
||||||
|
selectedExchange: string,
|
||||||
|
): Promise<AcceptWithdrawalResponse> {
|
||||||
|
const withdrawInfo = await getBankWithdrawalInfo(ws, talerWithdrawUri);
|
||||||
|
const exchangeWire = await getExchangePaytoUri(
|
||||||
|
ws,
|
||||||
|
selectedExchange,
|
||||||
|
withdrawInfo.wireTypes,
|
||||||
|
);
|
||||||
|
const reserve = await createReserve(ws, {
|
||||||
|
amount: withdrawInfo.amount,
|
||||||
|
bankWithdrawStatusUrl: withdrawInfo.extractedStatusUrl,
|
||||||
|
exchange: selectedExchange,
|
||||||
|
senderWire: withdrawInfo.senderWire,
|
||||||
|
exchangeWire: exchangeWire,
|
||||||
|
});
|
||||||
|
// We do this here, as the reserve should be registered before we return,
|
||||||
|
// so that we can redirect the user to the bank's status page.
|
||||||
|
await processReserveBankStatus(ws, reserve.reservePub);
|
||||||
|
console.log("acceptWithdrawal: returning");
|
||||||
|
return {
|
||||||
|
reservePub: reserve.reservePub,
|
||||||
|
confirmTransferUrl: withdrawInfo.confirmTransferUrl,
|
||||||
|
};
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of GNU Taler
|
This file is part of GNU Taler
|
||||||
(C) 2019 GNUnet e.V.
|
(C) 2019 Taler Systems S.A.
|
||||||
|
|
||||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -14,24 +14,41 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { parseTipUri } from "../util/taleruri";
|
import { parseTipUri } from "../util/taleruri";
|
||||||
import { TipStatus, getTimestampNow, OperationError } from "../types/walletTypes";
|
import {
|
||||||
import { TipPickupGetResponse, TipPlanchetDetail, TipResponse } from "../types/talerTypes";
|
TipStatus,
|
||||||
|
getTimestampNow,
|
||||||
|
OperationError,
|
||||||
|
} from "../types/walletTypes";
|
||||||
|
import {
|
||||||
|
TipPickupGetResponse,
|
||||||
|
TipPlanchetDetail,
|
||||||
|
TipResponse,
|
||||||
|
} from "../types/talerTypes";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
import { Stores, PlanchetRecord, WithdrawalSessionRecord, initRetryInfo, updateRetryInfoTimeout } from "../types/dbTypes";
|
import {
|
||||||
import { getExchangeWithdrawalInfo, getVerifiedWithdrawDenomList, processWithdrawSession } from "./withdraw";
|
Stores,
|
||||||
|
PlanchetRecord,
|
||||||
|
WithdrawalSessionRecord,
|
||||||
|
initRetryInfo,
|
||||||
|
updateRetryInfoTimeout,
|
||||||
|
} from "../types/dbTypes";
|
||||||
|
import {
|
||||||
|
getExchangeWithdrawalInfo,
|
||||||
|
getVerifiedWithdrawDenomList,
|
||||||
|
processWithdrawSession,
|
||||||
|
} from "./withdraw";
|
||||||
import { getTalerStampSec, extractTalerStampOrThrow } from "../util/helpers";
|
import { getTalerStampSec, extractTalerStampOrThrow } from "../util/helpers";
|
||||||
import { updateExchangeFromUrl } from "./exchanges";
|
import { updateExchangeFromUrl } from "./exchanges";
|
||||||
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
|
import { getRandomBytes, encodeCrock } from "../crypto/talerCrypto";
|
||||||
import { guardOperationException } from "./errors";
|
import { guardOperationException } from "./errors";
|
||||||
import { NotificationType } from "../types/notifications";
|
import { NotificationType } from "../types/notifications";
|
||||||
|
|
||||||
|
|
||||||
export async function getTipStatus(
|
export async function getTipStatus(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
talerTipUri: string): Promise<TipStatus> {
|
talerTipUri: string,
|
||||||
|
): Promise<TipStatus> {
|
||||||
const res = parseTipUri(talerTipUri);
|
const res = parseTipUri(talerTipUri);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
throw Error("invalid taler://tip URI");
|
throw Error("invalid taler://tip URI");
|
||||||
@ -134,19 +151,22 @@ export async function processTip(
|
|||||||
forceNow: boolean = false,
|
forceNow: boolean = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const onOpErr = (e: OperationError) => incrementTipRetry(ws, tipId, e);
|
const onOpErr = (e: OperationError) => incrementTipRetry(ws, tipId, e);
|
||||||
await guardOperationException(() => processTipImpl(ws, tipId, forceNow), onOpErr);
|
await guardOperationException(
|
||||||
|
() => processTipImpl(ws, tipId, forceNow),
|
||||||
|
onOpErr,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resetTipRetry(
|
async function resetTipRetry(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
tipId: string,
|
tipId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await ws.db.mutate(Stores.tips, tipId, (x) => {
|
await ws.db.mutate(Stores.tips, tipId, x => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processTipImpl(
|
async function processTipImpl(
|
||||||
@ -248,7 +268,7 @@ async function processTipImpl(
|
|||||||
const withdrawalSessionId = encodeCrock(getRandomBytes(32));
|
const withdrawalSessionId = encodeCrock(getRandomBytes(32));
|
||||||
|
|
||||||
const withdrawalSession: WithdrawalSessionRecord = {
|
const withdrawalSession: WithdrawalSessionRecord = {
|
||||||
denoms: planchets.map((x) => x.denomPub),
|
denoms: planchets.map(x => x.denomPub),
|
||||||
exchangeBaseUrl: tipRecord.exchangeUrl,
|
exchangeBaseUrl: tipRecord.exchangeUrl,
|
||||||
planchets: planchets,
|
planchets: planchets,
|
||||||
source: {
|
source: {
|
||||||
@ -258,29 +278,31 @@ async function processTipImpl(
|
|||||||
timestampStart: getTimestampNow(),
|
timestampStart: getTimestampNow(),
|
||||||
withdrawSessionId: withdrawalSessionId,
|
withdrawSessionId: withdrawalSessionId,
|
||||||
rawWithdrawalAmount: tipRecord.amount,
|
rawWithdrawalAmount: tipRecord.amount,
|
||||||
withdrawn: planchets.map((x) => false),
|
withdrawn: planchets.map(x => false),
|
||||||
totalCoinValue: Amounts.sum(planchets.map((p) => p.coinValue)).amount,
|
totalCoinValue: Amounts.sum(planchets.map(p => p.coinValue)).amount,
|
||||||
lastErrorPerCoin: {},
|
lastErrorPerCoin: {},
|
||||||
retryInfo: initRetryInfo(),
|
retryInfo: initRetryInfo(),
|
||||||
timestampFinish: undefined,
|
timestampFinish: undefined,
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await ws.db.runWithWriteTransaction(
|
||||||
|
[Stores.tips, Stores.withdrawalSession],
|
||||||
|
async tx => {
|
||||||
|
const tr = await tx.get(Stores.tips, tipId);
|
||||||
|
if (!tr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tr.pickedUp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tr.pickedUp = true;
|
||||||
|
tr.retryInfo = initRetryInfo(false);
|
||||||
|
|
||||||
await ws.db.runWithWriteTransaction([Stores.tips, Stores.withdrawalSession], async (tx) => {
|
await tx.put(Stores.tips, tr);
|
||||||
const tr = await tx.get(Stores.tips, tipId);
|
await tx.put(Stores.withdrawalSession, withdrawalSession);
|
||||||
if (!tr) {
|
},
|
||||||
return;
|
);
|
||||||
}
|
|
||||||
if (tr.pickedUp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tr.pickedUp = true;
|
|
||||||
tr.retryInfo = initRetryInfo(false);
|
|
||||||
|
|
||||||
await tx.put(Stores.tips, tr);
|
|
||||||
await tx.put(Stores.withdrawalSession, withdrawalSession);
|
|
||||||
});
|
|
||||||
|
|
||||||
await processWithdrawSession(ws, withdrawalSessionId);
|
await processWithdrawSession(ws, withdrawalSessionId);
|
||||||
|
|
||||||
|
32
src/operations/versions.ts
Normal file
32
src/operations/versions.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2019 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wallet protocol version spoken with the exchange
|
||||||
|
* and merchant.
|
||||||
|
*
|
||||||
|
* Uses libtool's current:revision:age versioning.
|
||||||
|
*/
|
||||||
|
export const WALLET_EXCHANGE_PROTOCOL_VERSION = "6";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache breaker that is appended to queries such as /keys and /wire
|
||||||
|
* to break through caching, if it has been accidentally/badly configured
|
||||||
|
* by the exchange.
|
||||||
|
*
|
||||||
|
* This is only a temporary measure.
|
||||||
|
*/
|
||||||
|
export const WALLET_CACHE_BREAKER_CLIENT_VERSION = "3";
|
@ -38,16 +38,11 @@ import { WithdrawOperationStatusResponse } from "../types/talerTypes";
|
|||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { parseWithdrawUri } from "../util/taleruri";
|
import { parseWithdrawUri } from "../util/taleruri";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import {
|
|
||||||
Database
|
|
||||||
} from "../util/query";
|
|
||||||
import {
|
import {
|
||||||
updateExchangeFromUrl,
|
updateExchangeFromUrl,
|
||||||
getExchangePaytoUri,
|
|
||||||
getExchangeTrust,
|
getExchangeTrust,
|
||||||
} from "./exchanges";
|
} from "./exchanges";
|
||||||
import { createReserve, processReserveBankStatus } from "./reserves";
|
import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions";
|
||||||
import { WALLET_PROTOCOL_VERSION } from "../wallet";
|
|
||||||
|
|
||||||
import * as LibtoolVersion from "../util/libtoolVersion";
|
import * as LibtoolVersion from "../util/libtoolVersion";
|
||||||
import { guardOperationException } from "./errors";
|
import { guardOperationException } from "./errors";
|
||||||
@ -103,7 +98,7 @@ export function getWithdrawDenomList(
|
|||||||
* Get information about a withdrawal from
|
* Get information about a withdrawal from
|
||||||
* a taler://withdraw URI by asking the bank.
|
* a taler://withdraw URI by asking the bank.
|
||||||
*/
|
*/
|
||||||
async function getBankWithdrawalInfo(
|
export async function getBankWithdrawalInfo(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
talerWithdrawUri: string,
|
talerWithdrawUri: string,
|
||||||
): Promise<BankWithdrawDetails> {
|
): Promise<BankWithdrawDetails> {
|
||||||
@ -130,33 +125,6 @@ async function getBankWithdrawalInfo(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function acceptWithdrawal(
|
|
||||||
ws: InternalWalletState,
|
|
||||||
talerWithdrawUri: string,
|
|
||||||
selectedExchange: string,
|
|
||||||
): Promise<AcceptWithdrawalResponse> {
|
|
||||||
const withdrawInfo = await getBankWithdrawalInfo(ws, talerWithdrawUri);
|
|
||||||
const exchangeWire = await getExchangePaytoUri(
|
|
||||||
ws,
|
|
||||||
selectedExchange,
|
|
||||||
withdrawInfo.wireTypes,
|
|
||||||
);
|
|
||||||
const reserve = await createReserve(ws, {
|
|
||||||
amount: withdrawInfo.amount,
|
|
||||||
bankWithdrawStatusUrl: withdrawInfo.extractedStatusUrl,
|
|
||||||
exchange: selectedExchange,
|
|
||||||
senderWire: withdrawInfo.senderWire,
|
|
||||||
exchangeWire: exchangeWire,
|
|
||||||
});
|
|
||||||
// We do this here, as the reserve should be registered before we return,
|
|
||||||
// so that we can redirect the user to the bank's status page.
|
|
||||||
await processReserveBankStatus(ws, reserve.reservePub);
|
|
||||||
console.log("acceptWithdrawal: returning");
|
|
||||||
return {
|
|
||||||
reservePub: reserve.reservePub,
|
|
||||||
confirmTransferUrl: withdrawInfo.confirmTransferUrl,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getPossibleDenoms(
|
async function getPossibleDenoms(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
@ -619,7 +587,7 @@ export async function getExchangeWithdrawalInfo(
|
|||||||
let versionMatch;
|
let versionMatch;
|
||||||
if (exchangeDetails.protocolVersion) {
|
if (exchangeDetails.protocolVersion) {
|
||||||
versionMatch = LibtoolVersion.compare(
|
versionMatch = LibtoolVersion.compare(
|
||||||
WALLET_PROTOCOL_VERSION,
|
WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
exchangeDetails.protocolVersion,
|
exchangeDetails.protocolVersion,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -629,7 +597,7 @@ export async function getExchangeWithdrawalInfo(
|
|||||||
versionMatch.currentCmp === -1
|
versionMatch.currentCmp === -1
|
||||||
) {
|
) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`wallet version ${WALLET_PROTOCOL_VERSION} might be outdated ` +
|
`wallet's support for exchange protocol version ${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` +
|
||||||
`(exchange has ${exchangeDetails.protocolVersion}), checking for updates`,
|
`(exchange has ${exchangeDetails.protocolVersion}), checking for updates`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -655,7 +623,7 @@ export async function getExchangeWithdrawalInfo(
|
|||||||
selectedDenoms,
|
selectedDenoms,
|
||||||
trustedAuditorPubs,
|
trustedAuditorPubs,
|
||||||
versionMatch,
|
versionMatch,
|
||||||
walletVersion: WALLET_PROTOCOL_VERSION,
|
walletVersion: WALLET_EXCHANGE_PROTOCOL_VERSION,
|
||||||
wireFees: exchangeWireInfo,
|
wireFees: exchangeWireInfo,
|
||||||
withdrawFee: acc,
|
withdrawFee: acc,
|
||||||
termsOfServiceAccepted: tosAccepted,
|
termsOfServiceAccepted: tosAccepted,
|
||||||
|
61
src/types/ReserveStatus.ts
Normal file
61
src/types/ReserveStatus.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2019 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Florian Dold <dold@taler.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
codecForString,
|
||||||
|
typecheckedCodec,
|
||||||
|
makeCodecForObject,
|
||||||
|
makeCodecForConstString,
|
||||||
|
makeCodecForUnion,
|
||||||
|
makeCodecForList,
|
||||||
|
} from "../util/codec";
|
||||||
|
import { runBlock } from "../util/helpers";
|
||||||
|
import { AmountString } from "./talerTypes";
|
||||||
|
import { ReserveTransaction, codecForReserveTransaction } from "./ReserveTransaction";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of a reserve.
|
||||||
|
*
|
||||||
|
* Schema type for the exchange's response to "/reserve/status".
|
||||||
|
*/
|
||||||
|
export interface ReserveStatus {
|
||||||
|
/**
|
||||||
|
* Balance left in the reserve.
|
||||||
|
*/
|
||||||
|
balance: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction history for the reserve.
|
||||||
|
*/
|
||||||
|
history: ReserveTransaction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const codecForReserveStatus = runBlock(() => (
|
||||||
|
typecheckedCodec<ReserveStatus>(
|
||||||
|
makeCodecForObject<ReserveStatus>()
|
||||||
|
.property("balance", codecForString)
|
||||||
|
.property("history", makeCodecForList(codecForReserveTransaction))
|
||||||
|
.build("ReserveStatus")
|
||||||
|
)
|
||||||
|
));
|
273
src/types/ReserveTransaction.ts
Normal file
273
src/types/ReserveTransaction.ts
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2019 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Florian Dold <dold@taler.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
codecForString,
|
||||||
|
typecheckedCodec,
|
||||||
|
makeCodecForObject,
|
||||||
|
makeCodecForConstString,
|
||||||
|
makeCodecForUnion,
|
||||||
|
} from "../util/codec";
|
||||||
|
import { runBlock } from "../util/helpers";
|
||||||
|
import {
|
||||||
|
AmountString,
|
||||||
|
Base32String,
|
||||||
|
EddsaSignatureString,
|
||||||
|
TimestampString,
|
||||||
|
EddsaPublicKeyString,
|
||||||
|
CoinPublicKeyString,
|
||||||
|
} from "./talerTypes";
|
||||||
|
|
||||||
|
export const enum ReserveTransactionType {
|
||||||
|
Withdraw = "WITHDRAW",
|
||||||
|
Deposit = "DEPOSIT",
|
||||||
|
Payback = "PAYBACK",
|
||||||
|
Closing = "CLOSING",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReserveWithdrawTransaction {
|
||||||
|
type: ReserveTransactionType.Withdraw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount withdrawn.
|
||||||
|
*/
|
||||||
|
amount: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash of the denomination public key of the coin.
|
||||||
|
*/
|
||||||
|
h_denom_pub: Base32String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash of the blinded coin to be signed
|
||||||
|
*/
|
||||||
|
h_coin_envelope: Base32String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature of 'TALER_WithdrawRequestPS' created with the reserves's
|
||||||
|
* private key.
|
||||||
|
*/
|
||||||
|
reserve_sig: EddsaSignatureString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fee that is charged for withdraw.
|
||||||
|
*/
|
||||||
|
withdraw_fee: AmountString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReserveDepositTransaction {
|
||||||
|
type: ReserveTransactionType.Deposit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount withdrawn.
|
||||||
|
*/
|
||||||
|
amount: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sender account payto://-URL
|
||||||
|
*/
|
||||||
|
sender_account_url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer details uniquely identifying the transfer.
|
||||||
|
*/
|
||||||
|
wire_reference: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of the incoming wire transfer.
|
||||||
|
*/
|
||||||
|
timestamp: TimestampString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReserveClosingTransaction {
|
||||||
|
type: ReserveTransactionType.Closing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closing balance.
|
||||||
|
*/
|
||||||
|
amount: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closing fee charged by the exchange.
|
||||||
|
*/
|
||||||
|
closing_fee: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wire transfer subject.
|
||||||
|
*/
|
||||||
|
wtid: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash of the wire account into which the funds were returned to.
|
||||||
|
*/
|
||||||
|
h_wire: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a signature over a
|
||||||
|
* struct TALER_ReserveCloseConfirmationPS with purpose
|
||||||
|
* TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED.
|
||||||
|
*/
|
||||||
|
exchange_sig: EddsaSignatureString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key used to create exchange_sig.
|
||||||
|
*/
|
||||||
|
exchange_pub: EddsaPublicKeyString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when the reserve was closed.
|
||||||
|
*/
|
||||||
|
timestamp: TimestampString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReservePaybackTransaction {
|
||||||
|
type: ReserveTransactionType.Payback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount paid back.
|
||||||
|
*/
|
||||||
|
amount: AmountString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receiver account details.
|
||||||
|
*/
|
||||||
|
receiver_account_details: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wire transfer identifier.
|
||||||
|
*/
|
||||||
|
wire_transfer: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a signature over
|
||||||
|
* a struct TALER_PaybackConfirmationPS with purpose
|
||||||
|
* TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK.
|
||||||
|
*/
|
||||||
|
exchange_sig: EddsaSignatureString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key used to create exchange_sig.
|
||||||
|
*/
|
||||||
|
exchange_pub: EddsaPublicKeyString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when the funds were paid back into the reserve.
|
||||||
|
*/
|
||||||
|
timestamp: TimestampString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the coin that was paid back.
|
||||||
|
*/
|
||||||
|
coin_pub: CoinPublicKeyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format of the exchange's transaction history for a reserve.
|
||||||
|
*/
|
||||||
|
export type ReserveTransaction =
|
||||||
|
| ReserveWithdrawTransaction
|
||||||
|
| ReserveDepositTransaction
|
||||||
|
| ReserveClosingTransaction
|
||||||
|
| ReservePaybackTransaction;
|
||||||
|
|
||||||
|
export const codecForReserveWithdrawTransaction = runBlock(() =>
|
||||||
|
typecheckedCodec<ReserveWithdrawTransaction>(
|
||||||
|
makeCodecForObject<ReserveWithdrawTransaction>()
|
||||||
|
.property("amount", codecForString)
|
||||||
|
.property("h_coin_envelope", codecForString)
|
||||||
|
.property("h_denom_pub", codecForString)
|
||||||
|
.property("reserve_sig", codecForString)
|
||||||
|
.property(
|
||||||
|
"type",
|
||||||
|
makeCodecForConstString(ReserveTransactionType.Withdraw),
|
||||||
|
)
|
||||||
|
.property("withdraw_fee", codecForString)
|
||||||
|
.build("ReserveWithdrawTransaction"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const codecForReserveDepositTransaction = runBlock(() =>
|
||||||
|
typecheckedCodec<ReserveDepositTransaction>(
|
||||||
|
makeCodecForObject<ReserveDepositTransaction>()
|
||||||
|
.property("amount", codecForString)
|
||||||
|
.property("sender_account_url", codecForString)
|
||||||
|
.property("timestamp", codecForString)
|
||||||
|
.property("wire_reference", codecForString)
|
||||||
|
.property("type", makeCodecForConstString(ReserveTransactionType.Deposit))
|
||||||
|
.build("ReserveDepositTransaction"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const codecForReserveClosingTransaction = runBlock(() =>
|
||||||
|
typecheckedCodec<ReserveClosingTransaction>(
|
||||||
|
makeCodecForObject<ReserveClosingTransaction>()
|
||||||
|
.property("amount", codecForString)
|
||||||
|
.property("closing_fee", codecForString)
|
||||||
|
.property("exchange_pub", codecForString)
|
||||||
|
.property("exchange_sig", codecForString)
|
||||||
|
.property("h_wire", codecForString)
|
||||||
|
.property("timestamp", codecForString)
|
||||||
|
.property("type", makeCodecForConstString(ReserveTransactionType.Closing))
|
||||||
|
.property("wtid", codecForString)
|
||||||
|
.build("ReserveClosingTransaction"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const codecForReservePaybackTransaction = runBlock(() =>
|
||||||
|
typecheckedCodec<ReservePaybackTransaction>(
|
||||||
|
makeCodecForObject<ReservePaybackTransaction>()
|
||||||
|
.property("amount", codecForString)
|
||||||
|
.property("coin_pub", codecForString)
|
||||||
|
.property("exchange_pub", codecForString)
|
||||||
|
.property("exchange_sig", codecForString)
|
||||||
|
.property("receiver_account_details", codecForString)
|
||||||
|
.property("timestamp", codecForString)
|
||||||
|
.property("type", makeCodecForConstString(ReserveTransactionType.Payback))
|
||||||
|
.property("wire_transfer", codecForString)
|
||||||
|
.build("ReservePaybackTransaction"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const codecForReserveTransaction = runBlock(() =>
|
||||||
|
typecheckedCodec<ReserveTransaction>(
|
||||||
|
makeCodecForUnion<ReserveTransaction>()
|
||||||
|
.discriminateOn("type")
|
||||||
|
.alternative(
|
||||||
|
ReserveTransactionType.Withdraw,
|
||||||
|
codecForReserveWithdrawTransaction,
|
||||||
|
)
|
||||||
|
.alternative(
|
||||||
|
ReserveTransactionType.Closing,
|
||||||
|
codecForReserveClosingTransaction,
|
||||||
|
)
|
||||||
|
.alternative(
|
||||||
|
ReserveTransactionType.Payback,
|
||||||
|
codecForReservePaybackTransaction,
|
||||||
|
)
|
||||||
|
.alternative(
|
||||||
|
ReserveTransactionType.Deposit,
|
||||||
|
codecForReserveDepositTransaction,
|
||||||
|
)
|
||||||
|
.build<ReserveTransaction>("ReserveTransaction"),
|
||||||
|
),
|
||||||
|
);
|
@ -30,7 +30,6 @@ import { AmountJson } from "./util/amounts";
|
|||||||
import * as Amounts from "./util/amounts";
|
import * as Amounts from "./util/amounts";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
acceptWithdrawal,
|
|
||||||
getWithdrawDetailsForUri,
|
getWithdrawDetailsForUri,
|
||||||
getExchangeWithdrawalInfo,
|
getExchangeWithdrawalInfo,
|
||||||
} from "./operations/withdraw";
|
} from "./operations/withdraw";
|
||||||
@ -82,7 +81,7 @@ import {
|
|||||||
getExchangePaytoUri,
|
getExchangePaytoUri,
|
||||||
acceptExchangeTermsOfService,
|
acceptExchangeTermsOfService,
|
||||||
} from "./operations/exchanges";
|
} from "./operations/exchanges";
|
||||||
import { processReserve } from "./operations/reserves";
|
import { processReserve, createTalerWithdrawReserve } from "./operations/reserves";
|
||||||
|
|
||||||
import { InternalWalletState } from "./operations/state";
|
import { InternalWalletState } from "./operations/state";
|
||||||
import { createReserve, confirmReserve } from "./operations/reserves";
|
import { createReserve, confirmReserve } from "./operations/reserves";
|
||||||
@ -111,15 +110,6 @@ import {
|
|||||||
applyRefund,
|
applyRefund,
|
||||||
} from "./operations/refund";
|
} from "./operations/refund";
|
||||||
|
|
||||||
/**
|
|
||||||
* Wallet protocol version spoken with the exchange
|
|
||||||
* and merchant.
|
|
||||||
*
|
|
||||||
* Uses libtool's current:revision:age versioning.
|
|
||||||
*/
|
|
||||||
export const WALLET_PROTOCOL_VERSION = "3:0:0";
|
|
||||||
|
|
||||||
export const WALLET_CACHE_BREAKER_CLIENT_VERSION = "3";
|
|
||||||
|
|
||||||
const builtinCurrencies: CurrencyRecord[] = [
|
const builtinCurrencies: CurrencyRecord[] = [
|
||||||
{
|
{
|
||||||
@ -690,7 +680,7 @@ export class Wallet {
|
|||||||
selectedExchange: string,
|
selectedExchange: string,
|
||||||
): Promise<AcceptWithdrawalResponse> {
|
): Promise<AcceptWithdrawalResponse> {
|
||||||
try {
|
try {
|
||||||
return acceptWithdrawal(this.ws, talerWithdrawUri, selectedExchange);
|
return createTalerWithdrawReserve(this.ws, talerWithdrawUri, selectedExchange);
|
||||||
} finally {
|
} finally {
|
||||||
this.latch.trigger();
|
this.latch.trigger();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"src/operations/return.ts",
|
"src/operations/return.ts",
|
||||||
"src/operations/state.ts",
|
"src/operations/state.ts",
|
||||||
"src/operations/tip.ts",
|
"src/operations/tip.ts",
|
||||||
|
"src/operations/versions.ts",
|
||||||
"src/operations/withdraw.ts",
|
"src/operations/withdraw.ts",
|
||||||
"src/types/ReserveStatus.ts",
|
"src/types/ReserveStatus.ts",
|
||||||
"src/types/ReserveTransaction.ts",
|
"src/types/ReserveTransaction.ts",
|
||||||
|
Loading…
Reference in New Issue
Block a user