wallet-core: compute full peer push payment fees
This commit is contained in:
parent
8309f803ab
commit
a3f9e86805
@ -70,6 +70,7 @@ import {
|
|||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";
|
import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";
|
||||||
import {
|
import {
|
||||||
|
DenominationRecord,
|
||||||
OperationStatus,
|
OperationStatus,
|
||||||
PeerPullPaymentIncomingStatus,
|
PeerPullPaymentIncomingStatus,
|
||||||
PeerPushPaymentCoinSelection,
|
PeerPushPaymentCoinSelection,
|
||||||
@ -97,6 +98,7 @@ import {
|
|||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
import { getPeerPaymentBalanceDetailsInTx } from "./balance.js";
|
import { getPeerPaymentBalanceDetailsInTx } from "./balance.js";
|
||||||
import { updateExchangeFromUrl } from "./exchanges.js";
|
import { updateExchangeFromUrl } from "./exchanges.js";
|
||||||
|
import { getTotalRefreshCost } from "./refresh.js";
|
||||||
import { internalCreateWithdrawalGroup } from "./withdraw.js";
|
import { internalCreateWithdrawalGroup } from "./withdraw.js";
|
||||||
|
|
||||||
const logger = new Logger("operations/peer-to-peer.ts");
|
const logger = new Logger("operations/peer-to-peer.ts");
|
||||||
@ -329,13 +331,83 @@ export async function selectPeerCoins(
|
|||||||
return { type: "failure", insufficientBalanceDetails: errDetails };
|
return { type: "failure", insufficientBalanceDetails: errDetails };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTotalPeerPaymentCost(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
pcs: PeerCoinSelectionDetails,
|
||||||
|
): Promise<AmountJson> {
|
||||||
|
return ws.db
|
||||||
|
.mktx((x) => [x.coins, x.denominations])
|
||||||
|
.runReadOnly(async (tx) => {
|
||||||
|
const costs: AmountJson[] = [];
|
||||||
|
for (let i = 0; i < pcs.coins.length; i++) {
|
||||||
|
const coin = await tx.coins.get(pcs.coins[i].coinPub);
|
||||||
|
if (!coin) {
|
||||||
|
throw Error("can't calculate payment cost, coin not found");
|
||||||
|
}
|
||||||
|
const denom = await tx.denominations.get([
|
||||||
|
coin.exchangeBaseUrl,
|
||||||
|
coin.denomPubHash,
|
||||||
|
]);
|
||||||
|
if (!denom) {
|
||||||
|
throw Error(
|
||||||
|
"can't calculate payment cost, denomination for coin not found",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
|
||||||
|
.iter(coin.exchangeBaseUrl)
|
||||||
|
.filter((x) =>
|
||||||
|
Amounts.isSameCurrency(
|
||||||
|
DenominationRecord.getValue(x),
|
||||||
|
pcs.coins[i].contribution,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const amountLeft = Amounts.sub(
|
||||||
|
DenominationRecord.getValue(denom),
|
||||||
|
pcs.coins[i].contribution,
|
||||||
|
).amount;
|
||||||
|
const refreshCost = getTotalRefreshCost(
|
||||||
|
allDenoms,
|
||||||
|
DenominationRecord.toDenomInfo(denom),
|
||||||
|
amountLeft,
|
||||||
|
);
|
||||||
|
costs.push(Amounts.parseOrThrow(pcs.coins[i].contribution));
|
||||||
|
costs.push(refreshCost);
|
||||||
|
}
|
||||||
|
const zero = Amounts.zeroOfAmount(pcs.coins[0].contribution);
|
||||||
|
return Amounts.sum([zero, ...costs]).amount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function preparePeerPushPayment(
|
export async function preparePeerPushPayment(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
req: PreparePeerPushPaymentRequest,
|
req: PreparePeerPushPaymentRequest,
|
||||||
): Promise<PreparePeerPushPaymentResponse> {
|
): Promise<PreparePeerPushPaymentResponse> {
|
||||||
// FIXME: look up for the exchange and calculate fee
|
const instructedAmount = Amounts.parseOrThrow(req.amount);
|
||||||
|
const coinSelRes: SelectPeerCoinsResult = await ws.db
|
||||||
|
.mktx((x) => [
|
||||||
|
x.exchanges,
|
||||||
|
x.contractTerms,
|
||||||
|
x.coins,
|
||||||
|
x.coinAvailability,
|
||||||
|
x.denominations,
|
||||||
|
x.refreshGroups,
|
||||||
|
x.peerPushPaymentInitiations,
|
||||||
|
])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const selRes = await selectPeerCoins(ws, tx, instructedAmount);
|
||||||
|
return selRes;
|
||||||
|
});
|
||||||
|
if (coinSelRes.type === "failure") {
|
||||||
|
throw TalerError.fromDetail(
|
||||||
|
TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE,
|
||||||
|
{
|
||||||
|
insufficientBalanceDetails: coinSelRes.insufficientBalanceDetails,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const totalAmount = await getTotalPeerPaymentCost(ws, coinSelRes.result);
|
||||||
return {
|
return {
|
||||||
amountEffective: req.amount,
|
amountEffective: Amounts.stringify(totalAmount),
|
||||||
amountRaw: req.amount,
|
amountRaw: req.amount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -954,7 +1026,7 @@ export async function processPeerPullInitiation(
|
|||||||
return {
|
return {
|
||||||
type: OperationAttemptResultType.Finished,
|
type: OperationAttemptResultType.Finished,
|
||||||
result: undefined,
|
result: undefined,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mergeReserve = await ws.db
|
const mergeReserve = await ws.db
|
||||||
|
Loading…
Reference in New Issue
Block a user