new balances API, remove defunct 'return funds to own account' implementation

This commit is contained in:
Florian Dold 2020-07-28 23:17:12 +05:30
parent 43655adff0
commit 732e764b37
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
9 changed files with 88 additions and 440 deletions

View File

@ -197,14 +197,7 @@ walletCli
.action(async (args) => { .action(async (args) => {
await withWallet(args, async (wallet) => { await withWallet(args, async (wallet) => {
const balance = await wallet.getBalances(); const balance = await wallet.getBalances();
if (args.balance.json) { console.log(JSON.stringify(balance, undefined, 2));
console.log(JSON.stringify(balance, undefined, 2));
} else {
const currencies = Object.keys(balance.byCurrency).sort();
for (const c of currencies) {
console.log(Amounts.stringify(balance.byCurrency[c].available));
}
}
}); });
}); });

View File

@ -17,7 +17,7 @@
/** /**
* Imports. * Imports.
*/ */
import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes"; import { BalancesResponse } from "../types/walletTypes";
import { TransactionHandle } from "../util/query"; import { TransactionHandle } from "../util/query";
import { InternalWalletState } from "./state"; import { InternalWalletState } from "./state";
import { Stores, CoinStatus } from "../types/dbTypes"; import { Stores, CoinStatus } from "../types/dbTypes";
@ -27,63 +27,49 @@ import { Logger } from "../util/logging";
const logger = new Logger("withdraw.ts"); const logger = new Logger("withdraw.ts");
interface WalletBalance {
available: AmountJson;
pendingIncoming: AmountJson;
pendingOutgoing: AmountJson;
}
/** /**
* Get balance information. * Get balance information.
*/ */
export async function getBalancesInsideTransaction( export async function getBalancesInsideTransaction(
ws: InternalWalletState, ws: InternalWalletState,
tx: TransactionHandle, tx: TransactionHandle,
): Promise<WalletBalance> { ): Promise<BalancesResponse> {
const balanceStore: Record<string, WalletBalance> = {};
/** /**
* Add amount to a balance field, both for * Add amount to a balance field, both for
* the slicing by exchange and currency. * the slicing by exchange and currency.
*/ */
function addTo( const initBalance = (currency: string): WalletBalance => {
balance: WalletBalance, const b = balanceStore[currency];
field: keyof WalletBalanceEntry, if (!b) {
amount: AmountJson, balanceStore[currency] = {
exchange: string, available: Amounts.getZero(currency),
): void { pendingIncoming: Amounts.getZero(currency),
const z = Amounts.getZero(amount.currency); pendingOutgoing: Amounts.getZero(currency),
const balanceIdentity = {
available: z,
paybackAmount: z,
pendingIncoming: z,
pendingPayment: z,
pendingIncomingDirty: z,
pendingIncomingRefresh: z,
pendingIncomingWithdraw: z,
};
let entryCurr = balance.byCurrency[amount.currency];
if (!entryCurr) {
balance.byCurrency[amount.currency] = entryCurr = {
...balanceIdentity,
}; };
} }
let entryEx = balance.byExchange[exchange]; return balanceStore[currency];
if (!entryEx) {
balance.byExchange[exchange] = entryEx = { ...balanceIdentity };
}
entryCurr[field] = Amounts.add(entryCurr[field], amount).amount;
entryEx[field] = Amounts.add(entryEx[field], amount).amount;
} }
const balanceStore = { // Initialize balance to zero, even if we didn't start withdrawing yet.
byCurrency: {},
byExchange: {},
};
await tx.iter(Stores.reserves).forEach((r) => { await tx.iter(Stores.reserves).forEach((r) => {
const z = Amounts.getZero(r.currency); initBalance(r.currency);
addTo(balanceStore, "available", z, r.exchangeBaseUrl);
}); });
await tx.iter(Stores.coins).forEach((c) => { await tx.iter(Stores.coins).forEach((c) => {
if (c.suspended) { // Only count fresh coins, as dormant coins will
return; // already be in a refresh session.
}
if (c.status === CoinStatus.Fresh) { if (c.status === CoinStatus.Fresh) {
addTo(balanceStore, "available", c.currentAmount, c.exchangeBaseUrl); const b = initBalance(c.currentAmount.currency);
b.available = Amounts.add(b.available, c.currentAmount).amount;
} }
}); });
@ -96,51 +82,38 @@ export async function getBalancesInsideTransaction(
for (let i = 0; i < r.oldCoinPubs.length; i++) { for (let i = 0; i < r.oldCoinPubs.length; i++) {
const session = r.refreshSessionPerCoin[i]; const session = r.refreshSessionPerCoin[i];
if (session) { if (session) {
addTo( const b = initBalance(session.amountRefreshOutput.currency);
balanceStore, // We are always assuming the refresh will succeed, thus we
"pendingIncoming", // report the output as available balance.
session.amountRefreshOutput, b.available = Amounts.add(session.amountRefreshOutput).amount;
session.exchangeBaseUrl,
);
addTo(
balanceStore,
"pendingIncomingRefresh",
session.amountRefreshOutput,
session.exchangeBaseUrl,
);
} }
} }
}); });
// FIXME: re-implement await tx.iter(Stores.withdrawalGroups).forEach((wds) => {
// await tx.iter(Stores.withdrawalGroups).forEach((wds) => { if (wds.timestampFinish) {
// let w = wds.totalCoinValue;
// for (let i = 0; i < wds.planchets.length; i++) {
// if (wds.withdrawn[i]) {
// const p = wds.planchets[i];
// if (p) {
// w = Amounts.sub(w, p.coinValue).amount;
// }
// }
// }
// addTo(balanceStore, "pendingIncoming", w, wds.exchangeBaseUrl);
// });
await tx.iter(Stores.purchases).forEach((t) => {
if (t.timestampFirstSuccessfulPay) {
return; return;
} }
for (const c of t.coinDepositPermissions) { const b = initBalance(wds.denomsSel.totalWithdrawCost.currency);
addTo( b.pendingIncoming = Amounts.add(b.pendingIncoming, wds.denomsSel.totalCoinValue).amount;
balanceStore,
"pendingPayment",
Amounts.parseOrThrow(c.contribution),
c.exchange_url,
);
}
}); });
return balanceStore; const balancesResponse: BalancesResponse = {
balances: [],
};
Object.keys(balanceStore).sort().forEach((c) => {
const v = balanceStore[c];
balancesResponse.balances.push({
available: Amounts.stringify(v.available),
pendingIncoming: Amounts.stringify(v.pendingIncoming),
pendingOutgoing: Amounts.stringify(v.pendingOutgoing),
hasPendingTransactions: false,
requiresUserInput: false,
});
})
return balancesResponse;
} }
/** /**
@ -148,7 +121,7 @@ export async function getBalancesInsideTransaction(
*/ */
export async function getBalances( export async function getBalances(
ws: InternalWalletState, ws: InternalWalletState,
): Promise<WalletBalance> { ): Promise<BalancesResponse> {
logger.trace("starting to compute balance"); logger.trace("starting to compute balance");
const wbal = await ws.db.runWithReadTransaction( const wbal = await ws.db.runWithReadTransaction(

View File

@ -15,7 +15,7 @@
*/ */
import { HttpRequestLibrary } from "../util/http"; import { HttpRequestLibrary } from "../util/http";
import { NextUrlResult, WalletBalance } from "../types/walletTypes"; import { NextUrlResult, BalancesResponse } from "../types/walletTypes";
import { CryptoApi, CryptoWorkerFactory } from "../crypto/workers/cryptoApi"; import { CryptoApi, CryptoWorkerFactory } from "../crypto/workers/cryptoApi";
import { AsyncOpMemoMap, AsyncOpMemoSingle } from "../util/asyncMemo"; import { AsyncOpMemoMap, AsyncOpMemoSingle } from "../util/asyncMemo";
import { Logger } from "../util/logging"; import { Logger } from "../util/logging";
@ -34,7 +34,7 @@ export class InternalWalletState {
memoGetPending: AsyncOpMemoSingle< memoGetPending: AsyncOpMemoSingle<
PendingOperationsResponse PendingOperationsResponse
> = new AsyncOpMemoSingle(); > = new AsyncOpMemoSingle();
memoGetBalance: AsyncOpMemoSingle<WalletBalance> = new AsyncOpMemoSingle(); memoGetBalance: AsyncOpMemoSingle<BalancesResponse> = new AsyncOpMemoSingle();
memoProcessRefresh: AsyncOpMemoMap<void> = new AsyncOpMemoMap(); memoProcessRefresh: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
memoProcessRecoup: AsyncOpMemoMap<void> = new AsyncOpMemoMap(); memoProcessRecoup: AsyncOpMemoMap<void> = new AsyncOpMemoMap();
cryptoApi: CryptoApi; cryptoApi: CryptoApi;

View File

@ -21,7 +21,7 @@
/** /**
* Imports. * Imports.
*/ */
import { OperationErrorDetails, WalletBalance } from "./walletTypes"; import { OperationErrorDetails, BalancesResponse } 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";
@ -243,7 +243,7 @@ export interface PendingOperationsResponse {
/** /**
* Current wallet balance, including pending balances. * Current wallet balance, including pending balances.
*/ */
walletBalance: WalletBalance; walletBalance: BalancesResponse;
/** /**
* When is the next pending operation due to be re-tried? * When is the next pending operation due to be re-tried?

View File

@ -146,48 +146,26 @@ export interface ExchangeWithdrawDetails {
walletVersion: string; walletVersion: string;
} }
/**
* Mapping from currency/exchange to detailed balance
* information.
*/
export interface WalletBalance {
/**
* Mapping from currency name to detailed balance info.
*/
byExchange: { [exchangeBaseUrl: string]: WalletBalanceEntry };
/** export interface Balance {
* Mapping from currency name to detailed balance info. available: AmountString;
*/ pendingIncoming: AmountString;
byCurrency: { [currency: string]: WalletBalanceEntry }; pendingOutgoing: AmountString;
// Does the balance for this currency have a pending
// transaction?
hasPendingTransactions: boolean;
// Is there a pending transaction that would affect the balance
// and requires user input?
requiresUserInput: boolean;
} }
/** export interface BalancesResponse {
* Detailed wallet balance for a particular currency. balances: Balance[];
*/
export interface WalletBalanceEntry {
/**
* Directly available amount.
*/
available: AmountJson;
/**
* Amount that we're waiting for (refresh, withdrawal).
*/
pendingIncoming: AmountJson;
/**
* Amount that's marked for a pending payment.
*/
pendingPayment: AmountJson;
/**
* Amount that was paid back and we could withdraw again.
*/
paybackAmount: AmountJson;
pendingIncomingWithdraw: AmountJson;
pendingIncomingRefresh: AmountJson;
pendingIncomingDirty: AmountJson;
} }
/** /**
* For terseness. * For terseness.
*/ */

View File

@ -60,7 +60,6 @@ import {
ReturnCoinsRequest, ReturnCoinsRequest,
SenderWireInfos, SenderWireInfos,
TipStatus, TipStatus,
WalletBalance,
PreparePayResult, PreparePayResult,
AcceptWithdrawalResponse, AcceptWithdrawalResponse,
PurchaseDetails, PurchaseDetails,
@ -70,6 +69,7 @@ import {
ManualWithdrawalDetails, ManualWithdrawalDetails,
GetExchangeTosResult, GetExchangeTosResult,
AcceptManualWithdrawalResult, AcceptManualWithdrawalResult,
BalancesResponse,
} from "./types/walletTypes"; } from "./types/walletTypes";
import { Logger } from "./util/logging"; import { Logger } from "./util/logging";
@ -515,7 +515,7 @@ export class Wallet {
/** /**
* Get detailed balance information, sliced by exchange and by currency. * Get detailed balance information, sliced by exchange and by currency.
*/ */
async getBalances(): Promise<WalletBalance> { async getBalances(): Promise<BalancesResponse> {
return this.ws.memoGetBalance.memo(() => getBalances(this.ws)); return this.ws.memoGetBalance.memo(() => getBalances(this.ws));
} }

View File

@ -29,8 +29,6 @@ import * as i18n from "../i18n";
import { AmountJson } from "../../util/amounts"; import { AmountJson } from "../../util/amounts";
import * as Amounts from "../../util/amounts"; import * as Amounts from "../../util/amounts";
import { WalletBalance, WalletBalanceEntry } from "../../types/walletTypes";
import { abbrev, renderAmount, PageLink } from "../renderHtml"; import { abbrev, renderAmount, PageLink } from "../renderHtml";
import * as wxApi from "../wxApi"; import * as wxApi from "../wxApi";
@ -40,6 +38,7 @@ import moment from "moment";
import { Timestamp } from "../../util/time"; import { Timestamp } from "../../util/time";
import { classifyTalerUri, TalerUriType } from "../../util/taleruri"; import { classifyTalerUri, TalerUriType } from "../../util/taleruri";
import { PermissionsCheckbox } from "./welcome"; import { PermissionsCheckbox } from "./welcome";
import { BalancesResponse, Balance } from "../../types/walletTypes";
// FIXME: move to newer react functions // FIXME: move to newer react functions
/* eslint-disable react/no-deprecated */ /* eslint-disable react/no-deprecated */
@ -172,7 +171,7 @@ function EmptyBalanceView(): JSX.Element {
} }
class WalletBalanceView extends React.Component<any, any> { class WalletBalanceView extends React.Component<any, any> {
private balance: WalletBalance; private balance: BalancesResponse;
private gotError = false; private gotError = false;
private canceler: (() => void) | undefined = undefined; private canceler: (() => void) | undefined = undefined;
private unmount = false; private unmount = false;
@ -196,7 +195,7 @@ class WalletBalanceView extends React.Component<any, any> {
return; return;
} }
this.updateBalanceRunning = true; this.updateBalanceRunning = true;
let balance: WalletBalance; let balance: BalancesResponse;
try { try {
balance = await wxApi.getBalance(); balance = await wxApi.getBalance();
} catch (e) { } catch (e) {
@ -219,10 +218,14 @@ class WalletBalanceView extends React.Component<any, any> {
this.setState({}); this.setState({});
} }
formatPending(entry: WalletBalanceEntry): JSX.Element { formatPending(entry: Balance): JSX.Element {
let incoming: JSX.Element | undefined; let incoming: JSX.Element | undefined;
let payment: JSX.Element | undefined; let payment: JSX.Element | undefined;
const available = Amounts.parseOrThrow(entry.available);
const pendingIncoming = Amounts.parseOrThrow(entry.pendingIncoming);
const pendingOutgoing = Amounts.parseOrThrow(entry.pendingOutgoing);
console.log( console.log(
"available: ", "available: ",
entry.pendingIncoming ? renderAmount(entry.available) : null, entry.pendingIncoming ? renderAmount(entry.available) : null,
@ -232,7 +235,7 @@ class WalletBalanceView extends React.Component<any, any> {
entry.pendingIncoming ? renderAmount(entry.pendingIncoming) : null, entry.pendingIncoming ? renderAmount(entry.pendingIncoming) : null,
); );
if (Amounts.isNonZero(entry.pendingIncoming)) { if (Amounts.isNonZero(pendingIncoming)) {
incoming = ( incoming = (
<i18n.Translate wrap="span"> <i18n.Translate wrap="span">
<span style={{ color: "darkgreen" }}> <span style={{ color: "darkgreen" }}>
@ -244,18 +247,6 @@ class WalletBalanceView extends React.Component<any, any> {
); );
} }
if (Amounts.isNonZero(entry.pendingPayment)) {
payment = (
<i18n.Translate wrap="span">
<span style={{ color: "red" }}>
{"-"}
{renderAmount(entry.pendingPayment)}
</span>{" "}
being spent
</i18n.Translate>
);
}
const l = [incoming, payment].filter((x) => x !== undefined); const l = [incoming, payment].filter((x) => x !== undefined);
if (l.length === 0) { if (l.length === 0) {
return <span />; return <span />;
@ -288,11 +279,11 @@ class WalletBalanceView extends React.Component<any, any> {
return <span></span>; return <span></span>;
} }
console.log(wallet); console.log(wallet);
const listing = Object.keys(wallet.byCurrency).map((key) => { const listing = wallet.balances.map((entry) => {
const entry: WalletBalanceEntry = wallet.byCurrency[key]; const av = Amounts.parseOrThrow(entry.available);
return ( return (
<p key={key}> <p key={av.currency}>
{bigAmount(entry.available)} {this.formatPending(entry)} {bigAmount(av)} {this.formatPending(entry)}
</p> </p>
); );
}); });
@ -314,7 +305,6 @@ function formatAndCapitalize(text: string): string {
return text; return text;
} }
const HistoryComponent = (props: any): JSX.Element => { const HistoryComponent = (props: any): JSX.Element => {
return <span>TBD</span>; return <span>TBD</span>;
}; };
@ -330,7 +320,6 @@ class WalletSettings extends React.Component<any, any> {
} }
} }
function reload(): void { function reload(): void {
try { try {
chrome.runtime.reload(); chrome.runtime.reload();

View File

@ -23,293 +23,8 @@
/** /**
* Imports. * Imports.
*/ */
import { AmountJson } from "../../util/amounts";
import { Amounts } from "../../util/amounts";
import { SenderWireInfos, WalletBalance } from "../../types/walletTypes";
import * as i18n from "../i18n";
import * as wire from "../../util/wire";
import { getBalance, getSenderWireInfos, returnCoins } from "../wxApi";
import { renderAmount } from "../renderHtml";
import * as React from "react"; import * as React from "react";
interface ReturnSelectionItemProps extends ReturnSelectionListProps {
exchangeUrl: string;
senderWireInfos: SenderWireInfos;
}
interface ReturnSelectionItemState {
selectedValue: string;
supportedWires: string[];
selectedWire: string;
currency: string;
}
class ReturnSelectionItem extends React.Component<
ReturnSelectionItemProps,
ReturnSelectionItemState
> {
constructor(props: ReturnSelectionItemProps) {
super(props);
const exchange = this.props.exchangeUrl;
const wireTypes = this.props.senderWireInfos.exchangeWireTypes;
const supportedWires = this.props.senderWireInfos.senderWires.filter(
(x) => {
return (
wireTypes[exchange] &&
wireTypes[exchange].indexOf((x as any).type) >= 0
);
},
);
this.state = {
currency: props.balance.byExchange[props.exchangeUrl].available.currency,
selectedValue: Amounts.stringify(
props.balance.byExchange[props.exchangeUrl].available,
),
selectedWire: "",
supportedWires,
};
}
render(): JSX.Element {
const exchange = this.props.exchangeUrl;
const byExchange = this.props.balance.byExchange;
const wireTypes = this.props.senderWireInfos.exchangeWireTypes;
return (
<div key={exchange}>
<h2>Exchange {exchange}</h2>
<p>Available amount: {renderAmount(byExchange[exchange].available)}</p>
<p>
Supported wire methods:{" "}
{wireTypes[exchange].length ? wireTypes[exchange].join(", ") : "none"}
</p>
<p>
Wire {""}
<input
type="text"
size={this.state.selectedValue.length || 1}
value={this.state.selectedValue}
onChange={(evt) =>
this.setState({ selectedValue: evt.target.value })
}
style={{ textAlign: "center" }}
/>{" "}
{this.props.balance.byExchange[exchange].available.currency} {""}
to account {""}
<select
value={this.state.selectedWire}
onChange={(evt) =>
this.setState({ selectedWire: evt.target.value })
}
>
<option style={{ display: "none" }}>Select account</option>
{this.state.supportedWires.map((w, n) => (
<option value={n.toString()} key={JSON.stringify(w)}>
{n + 1}: {wire.summarizeWire(w)}
</option>
))}
</select>
.
</p>
{this.state.selectedWire ? (
<button
className="pure-button button-success"
onClick={() => this.select()}
>
{i18n.str`Wire to bank account`}
</button>
) : null}
</div>
);
}
select(): void {
let val: number;
let selectedWire: number;
try {
val = Number.parseFloat(this.state.selectedValue);
selectedWire = Number.parseInt(this.state.selectedWire);
} catch (e) {
console.error(e);
return;
}
this.props.selectDetail({
amount: Amounts.fromFloat(val, this.state.currency),
exchange: this.props.exchangeUrl,
senderWire: this.state.supportedWires[selectedWire],
});
}
}
interface ReturnSelectionListProps {
balance: WalletBalance;
senderWireInfos: SenderWireInfos;
selectDetail(d: SelectedDetail): void;
}
class ReturnSelectionList extends React.Component<
ReturnSelectionListProps,
{}
> {
render(): JSX.Element {
const byExchange = this.props.balance.byExchange;
const exchanges = Object.keys(byExchange);
if (!exchanges.length) {
return (
<p className="errorbox">Currently no funds available to transfer.</p>
);
}
return (
<div>
{exchanges.map((e) => (
<ReturnSelectionItem key={e} exchangeUrl={e} {...this.props} />
))}
</div>
);
}
}
interface SelectedDetail {
amount: AmountJson;
senderWire: any;
exchange: string;
}
interface ReturnConfirmationProps {
detail: SelectedDetail;
cancel(): void;
confirm(): void;
}
class ReturnConfirmation extends React.Component<ReturnConfirmationProps, {}> {
render(): JSX.Element {
return (
<div>
<p>
Please confirm if you want to transmit{" "}
<strong>{renderAmount(this.props.detail.amount)}</strong> at {""}
{this.props.detail.exchange} to account {""}
<strong style={{ whiteSpace: "nowrap" }}>
{wire.summarizeWire(this.props.detail.senderWire)}
</strong>
.
</p>
<button
className="pure-button button-success"
onClick={() => this.props.confirm()}
>
{i18n.str`Confirm`}
</button>
<button className="pure-button" onClick={() => this.props.cancel()}>
{i18n.str`Cancel`}
</button>
</div>
);
}
}
interface ReturnCoinsState {
balance: WalletBalance | undefined;
senderWireInfos: SenderWireInfos | undefined;
selectedReturn: SelectedDetail | undefined;
/**
* Last confirmed detail, so we can show a nice box.
*/
lastConfirmedDetail: SelectedDetail | undefined;
}
class ReturnCoins extends React.Component<{}, ReturnCoinsState> {
constructor(props: {}) {
super(props);
const port = chrome.runtime.connect();
port.onMessage.addListener((msg: any) => {
if (msg.notify) {
console.log("got notified");
this.update();
}
});
this.update();
this.state = {} as any;
}
async update(): Promise<void> {
const balance = await getBalance();
const senderWireInfos = await getSenderWireInfos();
console.log("got swi", senderWireInfos);
console.log("got bal", balance);
this.setState({ balance, senderWireInfos });
}
selectDetail(d: SelectedDetail): void {
this.setState({ selectedReturn: d });
}
async confirm(): Promise<void> {
const selectedReturn = this.state.selectedReturn;
if (!selectedReturn) {
return;
}
await returnCoins(selectedReturn);
await this.update();
this.setState({
selectedReturn: undefined,
lastConfirmedDetail: selectedReturn,
});
}
async cancel(): Promise<void> {
this.setState({
selectedReturn: undefined,
lastConfirmedDetail: undefined,
});
}
render(): JSX.Element {
const balance = this.state.balance;
const senderWireInfos = this.state.senderWireInfos;
if (!balance || !senderWireInfos) {
return <span>...</span>;
}
if (this.state.selectedReturn) {
return (
<div id="main">
<ReturnConfirmation
detail={this.state.selectedReturn}
cancel={() => this.cancel()}
confirm={() => this.confirm()}
/>
</div>
);
}
return (
<div id="main">
<h1>Wire electronic cash back to own bank account</h1>
<p>
You can send coins back into your own bank account. Note that
you&apos;re acting as a merchant when doing this, and thus the same
fees apply.
</p>
{this.state.lastConfirmedDetail ? (
<p className="okaybox">
Transfer of {renderAmount(this.state.lastConfirmedDetail.amount)}{" "}
successfully initiated.
</p>
) : null}
<ReturnSelectionList
selectDetail={(d) => this.selectDetail(d)}
balance={balance}
senderWireInfos={senderWireInfos}
/>
</div>
);
}
}
export function createReturnCoinsPage(): JSX.Element { export function createReturnCoinsPage(): JSX.Element {
return <ReturnCoins />; return <span>Not implemented yet.</span>;
} }

View File

@ -34,12 +34,12 @@ import {
ConfirmPayResult, ConfirmPayResult,
SenderWireInfos, SenderWireInfos,
TipStatus, TipStatus,
WalletBalance,
PurchaseDetails, PurchaseDetails,
WalletDiagnostics, WalletDiagnostics,
PreparePayResult, PreparePayResult,
AcceptWithdrawalResponse, AcceptWithdrawalResponse,
ExtendedPermissionsResponse, ExtendedPermissionsResponse,
BalancesResponse,
} from "../types/walletTypes"; } from "../types/walletTypes";
/** /**
@ -185,7 +185,7 @@ export function resetDb(): Promise<void> {
/** /**
* Get balances for all currencies/exchanges. * Get balances for all currencies/exchanges.
*/ */
export function getBalance(): Promise<WalletBalance> { export function getBalance(): Promise<BalancesResponse> {
return callBackend("balances", {}); return callBackend("balances", {});
} }