fold checkPay into preparePay
This commit is contained in:
parent
51aa6d8146
commit
9297bbc825
@ -58,20 +58,20 @@ export async function runIntegrationTest(args: {
|
|||||||
|
|
||||||
console.log("payment status", paymentStatus);
|
console.log("payment status", paymentStatus);
|
||||||
|
|
||||||
const contractUrl = paymentStatus.contract_url;
|
const talerPayUri = paymentStatus.taler_pay_uri;
|
||||||
if (!contractUrl) {
|
if (!talerPayUri) {
|
||||||
throw Error("no contract URL in payment response");
|
throw Error("no taler://pay/ URI in payment response");
|
||||||
}
|
}
|
||||||
|
|
||||||
const proposalId = await myWallet.downloadProposal(contractUrl);
|
const preparePayResult = await myWallet.preparePay(talerPayUri);
|
||||||
|
|
||||||
console.log("proposal id", proposalId);
|
console.log("prepare pay result", preparePayResult);
|
||||||
|
|
||||||
const checkPayResult = await myWallet.checkPay(proposalId);
|
if (preparePayResult.status != "payment-possible") {
|
||||||
|
throw Error("payment not possible");
|
||||||
|
}
|
||||||
|
|
||||||
console.log("check pay result", checkPayResult);
|
const confirmPayResult = await myWallet.confirmPay(preparePayResult.proposalId, undefined);
|
||||||
|
|
||||||
const confirmPayResult = await myWallet.confirmPay(proposalId, undefined);
|
|
||||||
|
|
||||||
console.log("confirmPayResult", confirmPayResult);
|
console.log("confirmPayResult", confirmPayResult);
|
||||||
|
|
||||||
|
195
src/wallet.ts
195
src/wallet.ts
@ -85,7 +85,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
BenchmarkResult,
|
BenchmarkResult,
|
||||||
CheckPayResult,
|
|
||||||
CoinSelectionResult,
|
CoinSelectionResult,
|
||||||
CoinWithDenom,
|
CoinWithDenom,
|
||||||
ConfirmPayResult,
|
ConfirmPayResult,
|
||||||
@ -734,8 +733,15 @@ export class Wallet {
|
|||||||
return fu.href();
|
return fu.href();
|
||||||
}
|
}
|
||||||
|
|
||||||
async preparePay(url: string): Promise<PreparePayResult> {
|
|
||||||
const uriResult = parsePayUri(url);
|
/**
|
||||||
|
* Check if a payment for the given taler://pay/ URI is possible.
|
||||||
|
*
|
||||||
|
* If the payment is possible, the signature are already generated but not
|
||||||
|
* yet send to the merchant.
|
||||||
|
*/
|
||||||
|
async preparePay(talerPayUri: string): Promise<PreparePayResult> {
|
||||||
|
const uriResult = parsePayUri(talerPayUri);
|
||||||
|
|
||||||
if (!uriResult) {
|
if (!uriResult) {
|
||||||
return {
|
return {
|
||||||
@ -745,13 +751,11 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let proposalId: number;
|
let proposalId: number;
|
||||||
let checkResult: CheckPayResult;
|
|
||||||
try {
|
try {
|
||||||
proposalId = await this.downloadProposal(
|
proposalId = await this.downloadProposal(
|
||||||
uriResult.downloadUrl,
|
uriResult.downloadUrl,
|
||||||
uriResult.sessionId,
|
uriResult.sessionId,
|
||||||
);
|
);
|
||||||
checkResult = await this.checkPay(proposalId);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
status: "error",
|
status: "error",
|
||||||
@ -765,50 +769,84 @@ export class Wallet {
|
|||||||
|
|
||||||
console.log("proposal", proposal);
|
console.log("proposal", proposal);
|
||||||
|
|
||||||
if (uriResult.sessionId) {
|
// First check if we already payed for it.
|
||||||
const existingPayment = await this.q().getIndexed(
|
const purchase = await this.q().get(
|
||||||
Stores.purchases.fulfillmentUrlIndex,
|
Stores.purchases,
|
||||||
proposal.contractTerms.fulfillment_url,
|
proposal.contractTermsHash,
|
||||||
);
|
);
|
||||||
if (existingPayment) {
|
|
||||||
console.log("existing payment", existingPayment);
|
if (!purchase) {
|
||||||
await this.submitPay(
|
const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount);
|
||||||
existingPayment.contractTermsHash,
|
let wireFeeLimit;
|
||||||
uriResult.sessionId,
|
if (proposal.contractTerms.max_wire_fee) {
|
||||||
);
|
wireFeeLimit = Amounts.parseOrThrow(proposal.contractTerms.max_wire_fee);
|
||||||
|
} else {
|
||||||
|
wireFeeLimit = Amounts.getZero(paymentAmount.currency);
|
||||||
|
}
|
||||||
|
// If not already payed, check if we could pay for it.
|
||||||
|
const res = await this.getCoinsForPayment({
|
||||||
|
allowedAuditors: proposal.contractTerms.auditors,
|
||||||
|
allowedExchanges: proposal.contractTerms.exchanges,
|
||||||
|
depositFeeLimit: Amounts.parseOrThrow(proposal.contractTerms.max_fee),
|
||||||
|
paymentAmount,
|
||||||
|
wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1,
|
||||||
|
wireFeeLimit,
|
||||||
|
wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0,
|
||||||
|
wireMethod: proposal.contractTerms.wire_method,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
console.log("not confirming payment, insufficient coins");
|
||||||
return {
|
return {
|
||||||
status: "paid",
|
status: "insufficient-balance",
|
||||||
contractTerms: existingPayment.contractTerms,
|
contractTerms: proposal.contractTerms,
|
||||||
nextUrl: this.getNextUrl(existingPayment.contractTerms),
|
proposalId: proposal.id!,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (checkResult.status === "paid") {
|
// Only create speculative signature if we don't already have one for this proposal
|
||||||
const nextUrl = this.getNextUrl(proposal.contractTerms);
|
if (
|
||||||
return {
|
!this.speculativePayData ||
|
||||||
status: "paid",
|
(this.speculativePayData &&
|
||||||
contractTerms: proposal.contractTerms,
|
this.speculativePayData.proposalId !== proposalId)
|
||||||
proposalId: proposal.id!,
|
) {
|
||||||
nextUrl,
|
const { exchangeUrl, cds, totalAmount } = res;
|
||||||
};
|
const payCoinInfo = await this.cryptoApi.signDeposit(
|
||||||
}
|
proposal.contractTerms,
|
||||||
if (checkResult.status === "insufficient-balance") {
|
cds,
|
||||||
return {
|
totalAmount,
|
||||||
status: "insufficient-balance",
|
);
|
||||||
contractTerms: proposal.contractTerms,
|
this.speculativePayData = {
|
||||||
proposalId: proposal.id!,
|
exchangeUrl,
|
||||||
};
|
payCoinInfo,
|
||||||
}
|
proposal,
|
||||||
if (checkResult.status === "payment-possible") {
|
proposalId,
|
||||||
|
};
|
||||||
|
Wallet.enableTracing &&
|
||||||
|
console.log("created speculative pay data for payment");
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: "payment-possible",
|
status: "payment-possible",
|
||||||
contractTerms: proposal.contractTerms,
|
contractTerms: proposal.contractTerms,
|
||||||
proposalId: proposal.id!,
|
proposalId: proposal.id!,
|
||||||
totalFees: checkResult.coinSelection!.totalFees,
|
totalFees: res.totalFees,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw Error("not reached");
|
|
||||||
|
if (uriResult.sessionId) {
|
||||||
|
await this.submitPay(
|
||||||
|
purchase.contractTermsHash,
|
||||||
|
uriResult.sessionId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: "paid",
|
||||||
|
contractTerms: proposal.contractTerms,
|
||||||
|
proposalId: proposal.id!,
|
||||||
|
nextUrl: this.getNextUrl(purchase.contractTerms),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1088,85 +1126,6 @@ export class Wallet {
|
|||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if payment for an offer is possible, or if the offer has already
|
|
||||||
* been payed for.
|
|
||||||
*
|
|
||||||
* Also speculatively computes the signature for the payment to make the payment
|
|
||||||
* look faster to the user.
|
|
||||||
*/
|
|
||||||
async checkPay(proposalId: number): Promise<CheckPayResult> {
|
|
||||||
const proposal = await this.q().get(Stores.proposals, proposalId);
|
|
||||||
|
|
||||||
if (!proposal) {
|
|
||||||
throw Error(`proposal with id ${proposalId} not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First check if we already payed for it.
|
|
||||||
const purchase = await this.q().get(
|
|
||||||
Stores.purchases,
|
|
||||||
proposal.contractTermsHash,
|
|
||||||
);
|
|
||||||
if (purchase) {
|
|
||||||
Wallet.enableTracing && console.log("got purchase", purchase);
|
|
||||||
return { status: "paid" };
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount);
|
|
||||||
|
|
||||||
Wallet.enableTracing &&
|
|
||||||
console.log(
|
|
||||||
`checking if payment of ${JSON.stringify(paymentAmount)} is possible`,
|
|
||||||
);
|
|
||||||
|
|
||||||
let wireFeeLimit;
|
|
||||||
if (proposal.contractTerms.max_wire_fee) {
|
|
||||||
wireFeeLimit = Amounts.parseOrThrow(proposal.contractTerms.max_wire_fee);
|
|
||||||
} else {
|
|
||||||
wireFeeLimit = Amounts.getZero(paymentAmount.currency);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not already payed, check if we could pay for it.
|
|
||||||
const res = await this.getCoinsForPayment({
|
|
||||||
allowedAuditors: proposal.contractTerms.auditors,
|
|
||||||
allowedExchanges: proposal.contractTerms.exchanges,
|
|
||||||
depositFeeLimit: Amounts.parseOrThrow(proposal.contractTerms.max_fee),
|
|
||||||
paymentAmount,
|
|
||||||
wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1,
|
|
||||||
wireFeeLimit,
|
|
||||||
wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0,
|
|
||||||
wireMethod: proposal.contractTerms.wire_method,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
console.log("not confirming payment, insufficient coins");
|
|
||||||
return { status: "insufficient-balance" };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only create speculative signature if we don't already have one for this proposal
|
|
||||||
if (
|
|
||||||
!this.speculativePayData ||
|
|
||||||
(this.speculativePayData &&
|
|
||||||
this.speculativePayData.proposalId !== proposalId)
|
|
||||||
) {
|
|
||||||
const { exchangeUrl, cds, totalAmount } = res;
|
|
||||||
const payCoinInfo = await this.cryptoApi.signDeposit(
|
|
||||||
proposal.contractTerms,
|
|
||||||
cds,
|
|
||||||
totalAmount,
|
|
||||||
);
|
|
||||||
this.speculativePayData = {
|
|
||||||
exchangeUrl,
|
|
||||||
payCoinInfo,
|
|
||||||
proposal,
|
|
||||||
proposalId,
|
|
||||||
};
|
|
||||||
Wallet.enableTracing &&
|
|
||||||
console.log("created speculative pay data for payment");
|
|
||||||
}
|
|
||||||
|
|
||||||
return { status: "payment-possible", coinSelection: res };
|
|
||||||
}
|
|
||||||
|
|
||||||
private async sendReserveInfoToBank(reservePub: string) {
|
private async sendReserveInfoToBank(reservePub: string) {
|
||||||
const reserve = await this.q().get<ReserveRecord>(
|
const reserve = await this.q().get<ReserveRecord>(
|
||||||
|
@ -220,14 +220,6 @@ export function mkAmount(
|
|||||||
return { value, fraction, currency };
|
return { value, fraction, currency };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Possible results for checkPay.
|
|
||||||
*/
|
|
||||||
export interface CheckPayResult {
|
|
||||||
status: "paid" | "payment-possible" | "insufficient-balance";
|
|
||||||
coinSelection?: CoinSelectionResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result for confirmPay
|
* Result for confirmPay
|
||||||
*/
|
*/
|
||||||
@ -463,16 +455,15 @@ export type PreparePayResult =
|
|||||||
|
|
||||||
export interface PreparePayResultPaymentPossible {
|
export interface PreparePayResultPaymentPossible {
|
||||||
status: "payment-possible";
|
status: "payment-possible";
|
||||||
proposalId?: number;
|
proposalId: number;
|
||||||
contractTerms?: ContractTerms;
|
contractTerms: ContractTerms;
|
||||||
totalFees?: AmountJson;
|
totalFees: AmountJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PreparePayResultInsufficientBalance {
|
export interface PreparePayResultInsufficientBalance {
|
||||||
status: "insufficient-balance";
|
status: "insufficient-balance";
|
||||||
proposalId?: number;
|
proposalId: number;
|
||||||
contractTerms?: ContractTerms;
|
contractTerms: ContractTerms;
|
||||||
totalFees?: AmountJson;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PreparePayResultError {
|
export interface PreparePayResultError {
|
||||||
@ -482,8 +473,8 @@ export interface PreparePayResultError {
|
|||||||
|
|
||||||
export interface PreparePayResultPaid {
|
export interface PreparePayResultPaid {
|
||||||
status: "paid";
|
status: "paid";
|
||||||
proposalId?: number;
|
proposalId: number;
|
||||||
contractTerms?: ContractTerms;
|
contractTerms: ContractTerms;
|
||||||
nextUrl: string;
|
nextUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,10 +69,6 @@ export interface MessageMap {
|
|||||||
request: { proposalId: number; sessionId?: string };
|
request: { proposalId: number; sessionId?: string };
|
||||||
response: walletTypes.ConfirmPayResult;
|
response: walletTypes.ConfirmPayResult;
|
||||||
};
|
};
|
||||||
"check-pay": {
|
|
||||||
request: { proposalId: number };
|
|
||||||
response: walletTypes.CheckPayResult;
|
|
||||||
};
|
|
||||||
"exchange-info": {
|
"exchange-info": {
|
||||||
request: { baseUrl: string };
|
request: { baseUrl: string };
|
||||||
response: dbTypes.ExchangeRecord;
|
response: dbTypes.ExchangeRecord;
|
||||||
@ -205,7 +201,6 @@ export interface MessageMap {
|
|||||||
request: { talerPayUri: string };
|
request: { talerPayUri: string };
|
||||||
response: walletTypes.PreparePayResult;
|
response: walletTypes.PreparePayResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
"get-diagnostics": {
|
"get-diagnostics": {
|
||||||
request: { };
|
request: { };
|
||||||
response: walletTypes.WalletDiagnostics;
|
response: walletTypes.WalletDiagnostics;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
import * as i18n from "../../i18n";
|
import * as i18n from "../../i18n";
|
||||||
|
|
||||||
import { CheckPayResult, PreparePayResult } from "../../walletTypes";
|
import { PreparePayResult } from "../../walletTypes";
|
||||||
|
|
||||||
import { renderAmount, ProgressButton, registerMountPage } from "../renderHtml";
|
import { renderAmount, ProgressButton, registerMountPage } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
@ -29,13 +29,10 @@ import {
|
|||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
ExchangeRecord,
|
ExchangeRecord,
|
||||||
PreCoinRecord,
|
PreCoinRecord,
|
||||||
ProposalDownloadRecord,
|
|
||||||
PurchaseRecord,
|
|
||||||
ReserveRecord,
|
ReserveRecord,
|
||||||
} from "../dbTypes";
|
} from "../dbTypes";
|
||||||
import {
|
import {
|
||||||
BenchmarkResult,
|
BenchmarkResult,
|
||||||
CheckPayResult,
|
|
||||||
ConfirmPayResult,
|
ConfirmPayResult,
|
||||||
ReserveCreationInfo,
|
ReserveCreationInfo,
|
||||||
SenderWireInfos,
|
SenderWireInfos,
|
||||||
@ -45,10 +42,6 @@ import {
|
|||||||
WalletDiagnostics,
|
WalletDiagnostics,
|
||||||
} from "../walletTypes";
|
} from "../walletTypes";
|
||||||
|
|
||||||
import {
|
|
||||||
MerchantRefundPermission,
|
|
||||||
} from "../talerTypes";
|
|
||||||
|
|
||||||
import { MessageMap, MessageType } from "./messages";
|
import { MessageMap, MessageType } from "./messages";
|
||||||
|
|
||||||
|
|
||||||
@ -217,13 +210,6 @@ export function payback(coinPub: string): Promise<void> {
|
|||||||
return callBackend("payback-coin", { coinPub });
|
return callBackend("payback-coin", { coinPub });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if payment is possible or already done.
|
|
||||||
*/
|
|
||||||
export function checkPay(proposalId: number): Promise<CheckPayResult> {
|
|
||||||
return callBackend("check-pay", { proposalId });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pay for a proposal.
|
* Pay for a proposal.
|
||||||
*/
|
*/
|
||||||
|
@ -132,12 +132,6 @@ async function handleMessage(
|
|||||||
detail.sessionId,
|
detail.sessionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "check-pay": {
|
|
||||||
if (typeof detail.proposalId !== "number") {
|
|
||||||
throw Error("proposalId must be number");
|
|
||||||
}
|
|
||||||
return needsWallet().checkPay(detail.proposalId);
|
|
||||||
}
|
|
||||||
case "exchange-info": {
|
case "exchange-info": {
|
||||||
if (!detail.baseUrl) {
|
if (!detail.baseUrl) {
|
||||||
return Promise.resolve({ error: "bad url" });
|
return Promise.resolve({ error: "bad url" });
|
||||||
|
Loading…
Reference in New Issue
Block a user