aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/pay-peer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/pay-peer.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer.ts63
1 files changed, 38 insertions, 25 deletions
diff --git a/packages/taler-wallet-core/src/operations/pay-peer.ts b/packages/taler-wallet-core/src/operations/pay-peer.ts
index cc859f243..3d03c46db 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer.ts
@@ -18,7 +18,6 @@
* Imports.
*/
import {
- AbsoluteTime,
AcceptPeerPullPaymentRequest,
AcceptPeerPullPaymentResponse,
AcceptPeerPushPaymentRequest,
@@ -41,7 +40,6 @@ import {
constructPayPushUri,
ContractTermsUtil,
decodeCrock,
- Duration,
eddsaGetPublic,
encodeCrock,
ExchangePurseDeposits,
@@ -56,6 +54,7 @@ import {
Logger,
parsePayPullUri,
parsePayPushUri,
+ PayPeerInsufficientBalanceDetails,
PeerContractTerms,
PreparePeerPullPaymentRequest,
PreparePeerPullPaymentResponse,
@@ -132,6 +131,12 @@ interface CoinInfo {
ageCommitmentProof?: AgeCommitmentProof;
}
+export type SelectPeerCoinsResult =
+ | { type: "success"; result: PeerCoinSelection }
+ | {
+ type: "failure";
+ };
+
export async function selectPeerCoins(
ws: InternalWalletState,
tx: GetReadOnlyAccess<{
@@ -140,7 +145,7 @@ export async function selectPeerCoins(
coins: typeof WalletStoresV1.coins;
}>,
instructedAmount: AmountJson,
-): Promise<PeerCoinSelection | undefined> {
+): Promise<SelectPeerCoinsResult> {
const exchanges = await tx.exchanges.iter().toArray();
for (const exch of exchanges) {
if (exch.detailsPointer?.currency !== instructedAmount.currency) {
@@ -218,11 +223,11 @@ export async function selectPeerCoins(
coins: resCoins,
depositFees: depositFeesAcc,
};
- return res;
+ return { type: "success", result: res };
}
continue;
}
- return undefined;
+ return { type: "failure" };
}
export async function preparePeerPushPayment(
@@ -258,7 +263,7 @@ export async function initiatePeerToPeerPush(
pursePub: pursePair.pub,
});
- const coinSelRes: PeerCoinSelection | undefined = await ws.db
+ const coinSelRes: SelectPeerCoinsResult = await ws.db
.mktx((x) => [
x.exchanges,
x.contractTerms,
@@ -270,11 +275,13 @@ export async function initiatePeerToPeerPush(
x.peerPushPaymentInitiations,
])
.runReadWrite(async (tx) => {
- const sel = await selectPeerCoins(ws, tx, instructedAmount);
- if (!sel) {
- return undefined;
+ const selRes = await selectPeerCoins(ws, tx, instructedAmount);
+ if (selRes.type === "failure") {
+ return selRes;
}
+ const sel = selRes.result;
+
await spendCoins(ws, tx, {
allocationId: `txn:peer-push-debit:${pursePair.pub}`,
coinPubs: sel.coins.map((x) => x.coinPub),
@@ -304,11 +311,12 @@ export async function initiatePeerToPeerPush(
contractTermsRaw: contractTerms,
});
- return sel;
+ return selRes;
});
logger.info(`selected p2p coins (push): ${j2s(coinSelRes)}`);
- if (!coinSelRes) {
+ if (coinSelRes.type !== "success") {
+ // FIXME: use error code with details here
throw Error("insufficient balance");
}
@@ -322,14 +330,14 @@ export async function initiatePeerToPeerPush(
});
const depositSigsResp = await ws.cryptoApi.signPurseDeposits({
- exchangeBaseUrl: coinSelRes.exchangeBaseUrl,
+ exchangeBaseUrl: coinSelRes.result.exchangeBaseUrl,
pursePub: pursePair.pub,
- coins: coinSelRes.coins,
+ coins: coinSelRes.result.coins,
});
const createPurseUrl = new URL(
`purses/${pursePair.pub}/create`,
- coinSelRes.exchangeBaseUrl,
+ coinSelRes.result.exchangeBaseUrl,
);
const httpResp = await ws.http.postJson(createPurseUrl.href, {
@@ -355,9 +363,9 @@ export async function initiatePeerToPeerPush(
contractPriv: econtractResp.contractPriv,
mergePriv: mergePair.priv,
pursePub: pursePair.pub,
- exchangeBaseUrl: coinSelRes.exchangeBaseUrl,
+ exchangeBaseUrl: coinSelRes.result.exchangeBaseUrl,
talerUri: constructPayPushUri({
- exchangeBaseUrl: coinSelRes.exchangeBaseUrl,
+ exchangeBaseUrl: coinSelRes.result.exchangeBaseUrl,
contractPriv: econtractResp.contractPriv,
}),
transactionId: makeTransactionId(
@@ -627,7 +635,7 @@ export async function acceptPeerPullPayment(
const instructedAmount = Amounts.parseOrThrow(
peerPullInc.contractTerms.amount,
);
- const coinSelRes: PeerCoinSelection | undefined = await ws.db
+ const coinSelRes: SelectPeerCoinsResult = await ws.db
.mktx((x) => [
x.exchanges,
x.coins,
@@ -637,11 +645,13 @@ export async function acceptPeerPullPayment(
x.coinAvailability,
])
.runReadWrite(async (tx) => {
- const sel = await selectPeerCoins(ws, tx, instructedAmount);
- if (!sel) {
- return undefined;
+ const selRes = await selectPeerCoins(ws, tx, instructedAmount);
+ if (selRes.type !== "success") {
+ return selRes;
}
+ const sel = selRes.result;
+
await spendCoins(ws, tx, {
allocationId: `txn:peer-pull-debit:${req.peerPullPaymentIncomingId}`,
coinPubs: sel.coins.map((x) => x.coinPub),
@@ -660,25 +670,27 @@ export async function acceptPeerPullPayment(
pi.status = PeerPullPaymentIncomingStatus.Accepted;
await tx.peerPullPaymentIncoming.put(pi);
- return sel;
+ return selRes;
});
logger.info(`selected p2p coins (pull): ${j2s(coinSelRes)}`);
- if (!coinSelRes) {
+ if (coinSelRes.type !== "success") {
throw Error("insufficient balance");
}
const pursePub = peerPullInc.pursePub;
+ const coinSel = coinSelRes.result;
+
const depositSigsResp = await ws.cryptoApi.signPurseDeposits({
- exchangeBaseUrl: coinSelRes.exchangeBaseUrl,
+ exchangeBaseUrl: coinSel.exchangeBaseUrl,
pursePub,
- coins: coinSelRes.coins,
+ coins: coinSel.coins,
});
const purseDepositUrl = new URL(
`purses/${pursePub}/deposit`,
- coinSelRes.exchangeBaseUrl,
+ coinSel.exchangeBaseUrl,
);
const depositPayload: ExchangePurseDeposits = {
@@ -770,6 +782,7 @@ export async function preparePeerPullPayment(
amountRaw: req.amount,
};
}
+
/**
* Initiate a peer pull payment.
*/