summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-06-05 13:33:14 +0200
committerFlorian Dold <florian@dold.me>2023-06-05 13:33:14 +0200
commite671880b9e11b020c3fc797fb45e6e4b8ee3ee62 (patch)
tree454aff17188f80be64ea5825c41f7857ce785473
parentfda5a0ed87a6473a6b34bd1ac07d5f1d45dfbc19 (diff)
downloadwallet-core-e671880b9e11b020c3fc797fb45e6e4b8ee3ee62.tar.gz
wallet-core-e671880b9e11b020c3fc797fb45e6e4b8ee3ee62.tar.bz2
wallet-core-e671880b9e11b020c3fc797fb45e6e4b8ee3ee62.zip
wallet-core: use long-polling for P2P kyc
-rw-r--r--package.json2
-rw-r--r--packages/idb-bridge/package.json2
-rw-r--r--packages/taler-harness/package.json2
-rw-r--r--packages/taler-util/package.json2
-rw-r--r--packages/taler-util/src/transactions-types.ts4
-rw-r--r--packages/taler-wallet-cli/package.json2
-rw-r--r--packages/taler-wallet-core/package.json2
-rw-r--r--packages/taler-wallet-core/src/db.ts4
-rw-r--r--packages/taler-wallet-core/src/operations/common.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-common.ts8
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts200
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts209
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts40
-rw-r--r--packages/taler-wallet-embedded/package.json2
-rw-r--r--packages/web-util/package.json2
-rw-r--r--pnpm-lock.yaml36
16 files changed, 419 insertions, 99 deletions
diff --git a/package.json b/package.json
index 058d2d7f8..9ce6d628e 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,6 @@
"eslint": "^8.29.0",
"eslint-config-prettier": "^8.5.0",
"nx": "15.0.1",
- "prettier": "^2.7.1"
+ "prettier": "^2.8.8"
}
}
diff --git a/packages/idb-bridge/package.json b/packages/idb-bridge/package.json
index 63f1a5bbf..fc325cf35 100644
--- a/packages/idb-bridge/package.json
+++ b/packages/idb-bridge/package.json
@@ -25,7 +25,7 @@
"@types/node": "^18.11.17",
"ava": "^4.3.3",
"esm": "^3.2.25",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typescript": "^4.9.4"
},
diff --git a/packages/taler-harness/package.json b/packages/taler-harness/package.json
index b1def3b9a..e3e807cc2 100644
--- a/packages/taler-harness/package.json
+++ b/packages/taler-harness/package.json
@@ -33,7 +33,7 @@
"devDependencies": {
"@types/node": "^18.11.17",
"esbuild": "^0.17.7",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typescript": "^4.9.4"
},
diff --git a/packages/taler-util/package.json b/packages/taler-util/package.json
index 3a6c5a0a8..93a77b22b 100644
--- a/packages/taler-util/package.json
+++ b/packages/taler-util/package.json
@@ -62,7 +62,7 @@
"@types/node": "^18.11.17",
"ava": "^4.3.3",
"esbuild": "^0.17.7",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typescript": "^4.9.4"
},
diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts
index 5f5b9d112..82d847e80 100644
--- a/packages/taler-util/src/transactions-types.ts
+++ b/packages/taler-util/src/transactions-types.ts
@@ -345,6 +345,8 @@ export interface TransactionPeerPullCredit extends TransactionCommon {
* URI to send to the other party.
*/
talerUri: string;
+
+ kycUrl: string | undefined;
}
/**
@@ -413,6 +415,8 @@ export interface TransactionPeerPushCredit extends TransactionCommon {
* Amount that actually was (or will be) added to the wallet's balance.
*/
amountEffective: AmountString;
+
+ kycUrl: string | undefined;
}
export enum PaymentStatus {
diff --git a/packages/taler-wallet-cli/package.json b/packages/taler-wallet-cli/package.json
index 1a5364766..0daadd5e1 100644
--- a/packages/taler-wallet-cli/package.json
+++ b/packages/taler-wallet-cli/package.json
@@ -32,7 +32,7 @@
],
"devDependencies": {
"@types/node": "^18.11.17",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typedoc": "^0.23.16",
"typescript": "^4.9.4"
diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json
index 05fe89fd2..46e1c3667 100644
--- a/packages/taler-wallet-core/package.json
+++ b/packages/taler-wallet-core/package.json
@@ -64,7 +64,7 @@
"eslint-plugin-react-hooks": "^4.3.0",
"jed": "^1.1.1",
"po2json": "^0.4.5",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typedoc": "^0.23.16",
"typescript": "^4.9.4"
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 0e5d1c100..3f19822c8 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -1921,6 +1921,8 @@ export interface PeerPullPaymentInitiationRecord {
kycInfo?: KycPendingInfo;
+ kycUrl?: string;
+
withdrawalGroupId: string | undefined;
}
@@ -1989,6 +1991,8 @@ export interface PeerPushPaymentIncomingRecord {
currency: string | undefined;
kycInfo?: KycPendingInfo;
+
+ kycUrl?: string;
}
export enum PeerPullDebitRecordStatus {
diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts
index 203bf6788..ef5c54002 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -36,7 +36,6 @@ import {
TalerErrorDetail,
TombstoneIdStr,
TransactionIdStr,
- TransactionType,
} from "@gnu-taler/taler-util";
import {
WalletStoresV1,
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-common.ts b/packages/taler-wallet-core/src/operations/pay-peer-common.ts
index 4b1dd31a5..717b25f49 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-common.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-common.ts
@@ -25,19 +25,26 @@ import {
Codec,
CoinPublicKeyString,
CoinStatus,
+ HttpStatusCode,
Logger,
+ NotificationType,
PayPeerInsufficientBalanceDetails,
+ TalerError,
+ TalerErrorCode,
TalerProtocolTimestamp,
UnblindedSignature,
buildCodecForObject,
codecForAmountString,
codecForTimestamp,
codecOptional,
+ j2s,
strcmp,
} from "@gnu-taler/taler-util";
import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";
import {
DenominationRecord,
+ KycPendingInfo,
+ KycUserType,
PeerPushPaymentCoinSelection,
ReserveRecord,
} from "../db.js";
@@ -45,6 +52,7 @@ import { InternalWalletState } from "../internal-wallet-state.js";
import { checkDbInvariant } from "../util/invariants.js";
import { getPeerPaymentBalanceDetailsInTx } from "./balance.js";
import { getTotalRefreshCost } from "./refresh.js";
+import { OperationAttemptLongpollResult, OperationAttemptResult, OperationAttemptResultType } from "../util/retries.js";
const logger = new Logger("operations/peer-to-peer.ts");
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
index b9c9728a1..333202a69 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
@@ -26,6 +26,7 @@ import {
InitiatePeerPullCreditRequest,
InitiatePeerPullCreditResponse,
Logger,
+ TalerErrorCode,
TalerPreciseTimestamp,
TransactionAction,
TransactionMajorState,
@@ -33,12 +34,14 @@ import {
TransactionState,
TransactionType,
WalletAccountMergeFlags,
+ WalletKycUuid,
codecForAny,
codecForWalletKycUuid,
constructPayPullUri,
encodeCrock,
getRandomBytes,
j2s,
+ makeErrorDetail,
} from "@gnu-taler/taler-util";
import {
readSuccessResponseJsonOrErrorCode,
@@ -46,6 +49,8 @@ import {
throwUnexpectedRequestError,
} from "@gnu-taler/taler-util/http";
import {
+ KycPendingInfo,
+ KycUserType,
PeerPullPaymentInitiationRecord,
PeerPullPaymentInitiationStatus,
WithdrawalGroupStatus,
@@ -167,6 +172,75 @@ export async function queryPurseForPeerPullCredit(
};
}
+async function longpollKycStatus(
+ ws: InternalWalletState,
+ pursePub: string,
+ exchangeUrl: string,
+ kycInfo: KycPendingInfo,
+ userType: KycUserType,
+): Promise<OperationAttemptResult> {
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.PeerPullCredit,
+ pursePub,
+ });
+ const retryTag = constructTaskIdentifier({
+ tag: PendingTaskType.PeerPullCredit,
+ pursePub,
+ });
+
+ runLongpollAsync(ws, retryTag, async (ct) => {
+ const url = new URL(
+ `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`,
+ exchangeUrl,
+ );
+ url.searchParams.set("timeout_ms", "10000");
+ logger.info(`kyc url ${url.href}`);
+ const kycStatusRes = await ws.http.fetch(url.href, {
+ method: "GET",
+ cancellationToken: ct,
+ });
+ if (
+ kycStatusRes.status === HttpStatusCode.Ok ||
+ //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge
+ // remove after the exchange is fixed or clarified
+ kycStatusRes.status === HttpStatusCode.NoContent
+ ) {
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPullPaymentInitiations])
+ .runReadWrite(async (tx) => {
+ const peerIni = await tx.peerPullPaymentInitiations.get(
+ pursePub,
+ );
+ if (!peerIni) {
+ return;
+ }
+ if (
+ peerIni.status !== PeerPullPaymentInitiationStatus.PendingMergeKycRequired
+ ) {
+ return;
+ }
+ const oldTxState = computePeerPullCreditTransactionState(peerIni);
+ peerIni.status = PeerPullPaymentInitiationStatus.PendingCreatePurse;
+ const newTxState = computePeerPullCreditTransactionState(peerIni);
+ await tx.peerPullPaymentInitiations.put(peerIni);
+ return { oldTxState, newTxState };
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ return { ready: true };
+ } else if (kycStatusRes.status === HttpStatusCode.Accepted) {
+ // FIXME: Do we have to update the URL here?
+ return { ready: false };
+ } else {
+ throw Error(
+ `unexpected response from kyc-check (${kycStatusRes.status})`,
+ );
+ }
+ });
+ return {
+ type: OperationAttemptResultType.Longpoll,
+ };
+}
+
export async function processPeerPullCredit(
ws: InternalWalletState,
pursePub: string,
@@ -233,20 +307,16 @@ export async function processPeerPullCredit(
type: OperationAttemptResultType.Longpoll,
};
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: {
- const transactionId = constructTransactionIdentifier({
- tag: TransactionType.PeerPullCredit,
- pursePub: pullIni.pursePub,
- });
- if (pullIni.kycInfo) {
- await checkWithdrawalKycStatus(
- ws,
- pullIni.exchangeBaseUrl,
- transactionId,
- pullIni.kycInfo,
- "individual",
- );
+ if (!pullIni.kycInfo) {
+ throw Error("invalid state, kycInfo required");
}
- break;
+ return await longpollKycStatus(
+ ws,
+ pursePub,
+ pullIni.exchangeBaseUrl,
+ pullIni.kycInfo,
+ "individual",
+ );
}
case PeerPullPaymentInitiationStatus.PendingCreatePurse:
break;
@@ -325,26 +395,7 @@ export async function processPeerPullCredit(
const respJson = await httpResp.json();
const kycPending = codecForWalletKycUuid().decode(respJson);
logger.info(`kyc uuid response: ${j2s(kycPending)}`);
-
- await ws.db
- .mktx((x) => [x.peerPullPaymentInitiations])
- .runReadWrite(async (tx) => {
- const peerIni = await tx.peerPullPaymentInitiations.get(pursePub);
- if (!peerIni) {
- return;
- }
- peerIni.kycInfo = {
- paytoHash: kycPending.h_payto,
- requirementRow: kycPending.requirement_row,
- };
- peerIni.status =
- PeerPullPaymentInitiationStatus.PendingMergeKycRequired;
- await tx.peerPullPaymentInitiations.put(peerIni);
- });
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return processPeerPullCreditKycRequired(ws, pullIni, kycPending);
}
const resp = await readSuccessResponseJsonOrThrow(httpResp, codecForAny());
@@ -368,6 +419,89 @@ export async function processPeerPullCredit(
};
}
+async function processPeerPullCreditKycRequired(
+ ws: InternalWalletState,
+ peerIni: PeerPullPaymentInitiationRecord,
+ kycPending: WalletKycUuid,
+): Promise<OperationAttemptResult> {
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.PeerPullCredit,
+ pursePub: peerIni.pursePub,
+ });
+ const { pursePub } = peerIni;
+
+ const userType = "individual";
+ const url = new URL(
+ `kyc-check/${kycPending.requirement_row}/${kycPending.h_payto}/${userType}`,
+ peerIni.exchangeBaseUrl,
+ );
+
+ logger.info(`kyc url ${url.href}`);
+ const kycStatusRes = await ws.http.fetch(url.href, {
+ method: "GET",
+ });
+
+ if (
+ kycStatusRes.status === HttpStatusCode.Ok ||
+ //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge
+ // remove after the exchange is fixed or clarified
+ kycStatusRes.status === HttpStatusCode.NoContent
+ ) {
+ logger.warn("kyc requested, but already fulfilled");
+ return {
+ type: OperationAttemptResultType.Finished,
+ result: undefined,
+ };
+ } else if (kycStatusRes.status === HttpStatusCode.Accepted) {
+ const kycStatus = await kycStatusRes.json();
+ logger.info(`kyc status: ${j2s(kycStatus)}`);
+ const { transitionInfo, result } = await ws.db
+ .mktx((x) => [x.peerPullPaymentInitiations])
+ .runReadWrite(async (tx) => {
+ const peerInc = await tx.peerPullPaymentInitiations.get(
+ pursePub,
+ );
+ if (!peerInc) {
+ return {
+ transitionInfo: undefined,
+ result: OperationAttemptResult.finishedEmpty(),
+ };
+ }
+ const oldTxState = computePeerPullCreditTransactionState(peerInc);
+ peerInc.kycInfo = {
+ paytoHash: kycPending.h_payto,
+ requirementRow: kycPending.requirement_row,
+ };
+ peerInc.kycUrl = kycStatus.kyc_url;
+ peerInc.status = PeerPullPaymentInitiationStatus.PendingMergeKycRequired;
+ const newTxState = computePeerPullCreditTransactionState(peerInc);
+ await tx.peerPullPaymentInitiations.put(peerInc);
+ // We'll remove this eventually! New clients should rely on the
+ // kycUrl field of the transaction, not the error code.
+ const res: OperationAttemptResult = {
+ type: OperationAttemptResultType.Error,
+ errorDetail: makeErrorDetail(
+ TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED,
+ {
+ kycUrl: kycStatus.kyc_url,
+ },
+ ),
+ };
+ return {
+ transitionInfo: { oldTxState, newTxState },
+ result: res,
+ };
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ return {
+ type: OperationAttemptResultType.Pending,
+ result: undefined,
+ };
+ } else {
+ throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
+ }
+}
+
/**
* Check fees and available exchanges for a peer push payment initiation.
*/
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
index 69e0f3c27..91b0b6022 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
@@ -44,10 +44,16 @@ import {
TransactionMajorState,
TransactionMinorState,
TransactionState,
+ TalerError,
+ TalerErrorCode,
+ WalletKycUuid,
+ makeErrorDetail,
} from "@gnu-taler/taler-util";
import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import {
InternalWalletState,
+ KycPendingInfo,
+ KycUserType,
PeerPullDebitRecordStatus,
PeerPushPaymentIncomingRecord,
PeerPushPaymentIncomingStatus,
@@ -62,9 +68,12 @@ import {
queryCoinInfosForSelection,
talerPaytoFromExchangeReserve,
} from "./pay-peer-common.js";
-import { constructTransactionIdentifier, notifyTransition, stopLongpolling } from "./transactions.js";
import {
- checkWithdrawalKycStatus,
+ constructTransactionIdentifier,
+ notifyTransition,
+ stopLongpolling,
+} from "./transactions.js";
+import {
getExchangeWithdrawalInfo,
internalCreateWithdrawalGroup,
} from "./withdraw.js";
@@ -75,6 +84,7 @@ import {
constructTaskIdentifier,
} from "../util/retries.js";
import { assertUnreachable } from "../util/assertUnreachable.js";
+import { runLongpollAsync } from "./common.js";
const logger = new Logger("pay-peer-push-credit.ts");
@@ -215,6 +225,156 @@ export async function preparePeerPushCredit(
};
}
+async function longpollKycStatus(
+ ws: InternalWalletState,
+ peerPushPaymentIncomingId: string,
+ exchangeUrl: string,
+ kycInfo: KycPendingInfo,
+ userType: KycUserType,
+): Promise<OperationAttemptResult> {
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.PeerPushCredit,
+ peerPushPaymentIncomingId,
+ });
+ const retryTag = constructTaskIdentifier({
+ tag: PendingTaskType.PeerPushCredit,
+ peerPushPaymentIncomingId,
+ });
+
+ runLongpollAsync(ws, retryTag, async (ct) => {
+ const url = new URL(
+ `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`,
+ exchangeUrl,
+ );
+ url.searchParams.set("timeout_ms", "10000");
+ logger.info(`kyc url ${url.href}`);
+ const kycStatusRes = await ws.http.fetch(url.href, {
+ method: "GET",
+ cancellationToken: ct,
+ });
+ if (
+ kycStatusRes.status === HttpStatusCode.Ok ||
+ //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge
+ // remove after the exchange is fixed or clarified
+ kycStatusRes.status === HttpStatusCode.NoContent
+ ) {
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPushPaymentIncoming])
+ .runReadWrite(async (tx) => {
+ const peerInc = await tx.peerPushPaymentIncoming.get(
+ peerPushPaymentIncomingId,
+ );
+ if (!peerInc) {
+ return;
+ }
+ if (
+ peerInc.status !==
+ PeerPushPaymentIncomingStatus.PendingMergeKycRequired
+ ) {
+ return;
+ }
+ const oldTxState = computePeerPushCreditTransactionState(peerInc);
+ peerInc.status = PeerPushPaymentIncomingStatus.PendingMerge;
+ const newTxState = computePeerPushCreditTransactionState(peerInc);
+ await tx.peerPushPaymentIncoming.put(peerInc);
+ return { oldTxState, newTxState };
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ return { ready: true };
+ } else if (kycStatusRes.status === HttpStatusCode.Accepted) {
+ // FIXME: Do we have to update the URL here?
+ return { ready: false };
+ } else {
+ throw Error(
+ `unexpected response from kyc-check (${kycStatusRes.status})`,
+ );
+ }
+ });
+ return {
+ type: OperationAttemptResultType.Longpoll,
+ };
+}
+
+async function processPeerPushCreditKycRequired(
+ ws: InternalWalletState,
+ peerInc: PeerPushPaymentIncomingRecord,
+ kycPending: WalletKycUuid,
+): Promise<OperationAttemptResult> {
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.PeerPushCredit,
+ peerPushPaymentIncomingId: peerInc.peerPushPaymentIncomingId,
+ });
+ const { peerPushPaymentIncomingId } = peerInc;
+
+ const userType = "individual";
+ const url = new URL(
+ `kyc-check/${kycPending.requirement_row}/${kycPending.h_payto}/${userType}`,
+ peerInc.exchangeBaseUrl,
+ );
+
+ logger.info(`kyc url ${url.href}`);
+ const kycStatusRes = await ws.http.fetch(url.href, {
+ method: "GET",
+ });
+
+ if (
+ kycStatusRes.status === HttpStatusCode.Ok ||
+ //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge
+ // remove after the exchange is fixed or clarified
+ kycStatusRes.status === HttpStatusCode.NoContent
+ ) {
+ logger.warn("kyc requested, but already fulfilled");
+ return {
+ type: OperationAttemptResultType.Finished,
+ result: undefined,
+ };
+ } else if (kycStatusRes.status === HttpStatusCode.Accepted) {
+ const kycStatus = await kycStatusRes.json();
+ logger.info(`kyc status: ${j2s(kycStatus)}`);
+ const { transitionInfo, result } = await ws.db
+ .mktx((x) => [x.peerPushPaymentIncoming])
+ .runReadWrite(async (tx) => {
+ const peerInc = await tx.peerPushPaymentIncoming.get(
+ peerPushPaymentIncomingId,
+ );
+ if (!peerInc) {
+ return {
+ transitionInfo: undefined,
+ result: OperationAttemptResult.finishedEmpty(),
+ };
+ }
+ const oldTxState = computePeerPushCreditTransactionState(peerInc);
+ peerInc.kycInfo = {
+ paytoHash: kycPending.h_payto,
+ requirementRow: kycPending.requirement_row,
+ };
+ peerInc.kycUrl = kycStatus.kyc_url;
+ peerInc.status = PeerPushPaymentIncomingStatus.PendingMergeKycRequired;
+ const newTxState = computePeerPushCreditTransactionState(peerInc);
+ await tx.peerPushPaymentIncoming.put(peerInc);
+ // We'll remove this eventually! New clients should rely on the
+ // kycUrl field of the transaction, not the error code.
+ const res: OperationAttemptResult = {
+ type: OperationAttemptResultType.Error,
+ errorDetail: makeErrorDetail(
+ TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED,
+ {
+ kycUrl: kycStatus.kyc_url,
+ },
+ ),
+ };
+ return {
+ transitionInfo: { oldTxState, newTxState },
+ result: res,
+ };
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ return result;
+ } else {
+ throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
+ }
+}
+
export async function processPeerPushCredit(
ws: InternalWalletState,
peerPushPaymentIncomingId: string,
@@ -246,17 +406,15 @@ export async function processPeerPushCredit(
const amount = Amounts.parseOrThrow(contractTerms.amount);
if (
- peerInc.status === PeerPushPaymentIncomingStatus.PendingMergeKycRequired &&
- peerInc.kycInfo
+ peerInc.status === PeerPushPaymentIncomingStatus.PendingMergeKycRequired
) {
- const txId = constructTransactionIdentifier({
- tag: TransactionType.PeerPushCredit,
- peerPushPaymentIncomingId: peerInc.peerPushPaymentIncomingId,
- });
- await checkWithdrawalKycStatus(
+ if (!peerInc.kycInfo) {
+ throw Error("invalid state, kycInfo required");
+ }
+ return await longpollKycStatus(
ws,
+ peerPushPaymentIncomingId,
peerInc.exchangeBaseUrl,
- txId,
peerInc.kycInfo,
"individual",
);
@@ -298,33 +456,16 @@ export async function processPeerPushCredit(
reserve_sig: sigRes.accountSig,
};
- const mergeHttpResp = await ws.http.postJson(mergePurseUrl.href, mergeReq);
+ const mergeHttpResp = await ws.http.fetch(mergePurseUrl.href, {
+ method: "POST",
+ body: mergeReq,
+ });
if (mergeHttpResp.status === HttpStatusCode.UnavailableForLegalReasons) {
const respJson = await mergeHttpResp.json();
const kycPending = codecForWalletKycUuid().decode(respJson);
logger.info(`kyc uuid response: ${j2s(kycPending)}`);
-
- await ws.db
- .mktx((x) => [x.peerPushPaymentIncoming])
- .runReadWrite(async (tx) => {
- const peerInc = await tx.peerPushPaymentIncoming.get(
- peerPushPaymentIncomingId,
- );
- if (!peerInc) {
- return;
- }
- peerInc.kycInfo = {
- paytoHash: kycPending.h_payto,
- requirementRow: kycPending.requirement_row,
- };
- peerInc.status = PeerPushPaymentIncomingStatus.PendingMergeKycRequired;
- await tx.peerPushPaymentIncoming.put(peerInc);
- });
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ processPeerPushCreditKycRequired(ws, peerInc, kycPending);
}
logger.trace(`merge request: ${j2s(mergeReq)}`);
@@ -412,7 +553,6 @@ export async function confirmPeerPushCredit(
};
}
-
export async function processPeerPullDebit(
ws: InternalWalletState,
peerPullPaymentIncomingId: string,
@@ -483,7 +623,6 @@ export async function processPeerPullDebit(
};
}
-
export async function suspendPeerPushCreditTransaction(
ws: InternalWalletState,
peerPushPaymentIncomingId: string,
@@ -767,4 +906,4 @@ export function computePeerPushCreditTransactionActions(
default:
assertUnreachable(pushCreditRecord.status);
}
-} \ No newline at end of file
+}
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 1bd024d28..6fe0f1390 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -117,10 +117,38 @@ import {
suspendWithdrawalTransaction,
computeWithdrawalTransactionActions,
} from "./withdraw.js";
-import { computePeerPullCreditTransactionState, computePeerPullCreditTransactionActions, suspendPeerPullCreditTransaction, failPeerPullCreditTransaction, resumePeerPullCreditTransaction, abortPeerPullCreditTransaction } from "./pay-peer-pull-credit.js";
-import { computePeerPullDebitTransactionState, computePeerPullDebitTransactionActions, suspendPeerPullDebitTransaction, failPeerPullDebitTransaction, resumePeerPullDebitTransaction, abortPeerPullDebitTransaction } from "./pay-peer-pull-debit.js";
-import { computePeerPushCreditTransactionState, computePeerPushCreditTransactionActions, suspendPeerPushCreditTransaction, failPeerPushCreditTransaction, resumePeerPushCreditTransaction, abortPeerPushCreditTransaction } from "./pay-peer-push-credit.js";
-import { computePeerPushDebitTransactionState, computePeerPushDebitTransactionActions, suspendPeerPushDebitTransaction, failPeerPushDebitTransaction, resumePeerPushDebitTransaction, abortPeerPushDebitTransaction } from "./pay-peer-push-debit.js";
+import {
+ computePeerPullCreditTransactionState,
+ computePeerPullCreditTransactionActions,
+ suspendPeerPullCreditTransaction,
+ failPeerPullCreditTransaction,
+ resumePeerPullCreditTransaction,
+ abortPeerPullCreditTransaction,
+} from "./pay-peer-pull-credit.js";
+import {
+ computePeerPullDebitTransactionState,
+ computePeerPullDebitTransactionActions,
+ suspendPeerPullDebitTransaction,
+ failPeerPullDebitTransaction,
+ resumePeerPullDebitTransaction,
+ abortPeerPullDebitTransaction,
+} from "./pay-peer-pull-debit.js";
+import {
+ computePeerPushCreditTransactionState,
+ computePeerPushCreditTransactionActions,
+ suspendPeerPushCreditTransaction,
+ failPeerPushCreditTransaction,
+ resumePeerPushCreditTransaction,
+ abortPeerPushCreditTransaction,
+} from "./pay-peer-push-credit.js";
+import {
+ computePeerPushDebitTransactionState,
+ computePeerPushDebitTransactionActions,
+ suspendPeerPushDebitTransaction,
+ failPeerPushDebitTransaction,
+ resumePeerPushDebitTransaction,
+ abortPeerPushDebitTransaction,
+} from "./pay-peer-push-debit.js";
const logger = new Logger("taler-wallet-core:transactions.ts");
@@ -510,6 +538,7 @@ function buildTransactionForPeerPullCredit(
tag: TransactionType.PeerPullCredit,
pursePub: pullCredit.pursePub,
}),
+ kycUrl: pullCredit.kycUrl,
...(wsrOrt?.lastError
? {
error: silentWithdrawalErrorForInvoice
@@ -541,6 +570,7 @@ function buildTransactionForPeerPullCredit(
tag: TransactionType.PeerPullCredit,
pursePub: pullCredit.pursePub,
}),
+ kycUrl: pullCredit.kycUrl,
...(pullCreditOrt?.lastError ? { error: pullCreditOrt.lastError } : {}),
};
}
@@ -573,6 +603,7 @@ function buildTransactionForPeerPushCredit(
tag: TransactionType.PeerPushCredit,
peerPushPaymentIncomingId: pushInc.peerPushPaymentIncomingId,
}),
+ kycUrl: pushInc.kycUrl,
...(wsrOrt?.lastError ? { error: wsrOrt.lastError } : {}),
};
}
@@ -589,6 +620,7 @@ function buildTransactionForPeerPushCredit(
expiration: peerContractTerms.purse_expiration,
summary: peerContractTerms.summary,
},
+ kycUrl: pushInc.kycUrl,
timestamp: pushInc.timestamp,
transactionId: constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
diff --git a/packages/taler-wallet-embedded/package.json b/packages/taler-wallet-embedded/package.json
index a57a4d6d7..0e8a13a82 100644
--- a/packages/taler-wallet-embedded/package.json
+++ b/packages/taler-wallet-embedded/package.json
@@ -29,7 +29,7 @@
"devDependencies": {
"@types/node": "^18.11.17",
"esbuild": "^0.17.7",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2"
},
"dependencies": {
diff --git a/packages/web-util/package.json b/packages/web-util/package.json
index 0041e73d0..c13e43965 100644
--- a/packages/web-util/package.json
+++ b/packages/web-util/package.json
@@ -53,7 +53,7 @@
"postcss-load-config": "^4.0.1",
"preact": "10.11.3",
"preact-render-to-string": "^5.2.6",
- "prettier": "^2.5.1",
+ "prettier": "^2.8.8",
"rimraf": "^3.0.2",
"sass": "1.56.1",
"swr": "2.0.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6e705ee90..5c5e8feca 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,7 +11,7 @@ importers:
eslint: ^8.29.0
eslint-config-prettier: ^8.5.0
nx: 15.0.1
- prettier: ^2.7.1
+ prettier: ^2.8.8
devDependencies:
'@babel/core': 7.13.16
'@linaria/esbuild': 3.0.0-beta.23
@@ -20,7 +20,7 @@ importers:
eslint: 8.29.0
eslint-config-prettier: 8.5.0_eslint@8.29.0
nx: 15.0.1
- prettier: 2.7.1
+ prettier: 2.8.8
packages/anastasis-core:
specifiers:
@@ -209,7 +209,7 @@ importers:
'@types/node': ^18.11.17
ava: ^4.3.3
esm: ^3.2.25
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
typescript: ^4.9.4
@@ -219,7 +219,7 @@ importers:
'@types/node': 18.11.17
ava: 4.3.3
esm: 3.2.25
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
typescript: 4.9.4
@@ -391,7 +391,7 @@ importers:
'@types/node': ^18.11.17
axios: ^0.27.2
esbuild: ^0.17.7
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
typescript: ^4.9.4
@@ -403,7 +403,7 @@ importers:
devDependencies:
'@types/node': 18.11.17
esbuild: 0.17.7
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
typescript: 4.9.4
@@ -415,7 +415,7 @@ importers:
esbuild: ^0.17.7
fflate: ^0.7.4
jed: ^1.1.1
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
typescript: ^4.9.4
@@ -428,7 +428,7 @@ importers:
'@types/node': 18.11.17
ava: 4.3.3
esbuild: 0.17.7
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
typescript: 4.9.4
@@ -437,7 +437,7 @@ importers:
'@gnu-taler/taler-util': workspace:*
'@gnu-taler/taler-wallet-core': workspace:*
'@types/node': ^18.11.17
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
typedoc: ^0.23.16
@@ -448,7 +448,7 @@ importers:
tslib: 2.4.0
devDependencies:
'@types/node': 18.11.17
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
typedoc: 0.23.18_typescript@4.9.4
typescript: 4.9.4
@@ -475,7 +475,7 @@ importers:
fflate: ^0.7.4
jed: ^1.1.1
po2json: ^0.4.5
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
typedoc: ^0.23.16
@@ -503,7 +503,7 @@ importers:
eslint-plugin-react-hooks: 4.6.0_eslint@8.26.0
jed: 1.1.1
po2json: 0.4.5
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
typedoc: 0.23.18_typescript@4.9.4
typescript: 4.9.4
@@ -515,7 +515,7 @@ importers:
'@gnu-taler/taler-wallet-core': workspace:*
'@types/node': ^18.11.17
esbuild: ^0.17.7
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
tslib: ^2.4.0
dependencies:
@@ -526,7 +526,7 @@ importers:
devDependencies:
'@types/node': 18.11.17
esbuild: 0.17.7
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
packages/taler-wallet-webextension:
@@ -621,7 +621,7 @@ importers:
postcss-load-config: ^4.0.1
preact: 10.11.3
preact-render-to-string: ^5.2.6
- prettier: ^2.5.1
+ prettier: ^2.8.8
rimraf: ^3.0.2
sass: 1.56.1
swr: 2.0.3
@@ -655,7 +655,7 @@ importers:
postcss-load-config: 4.0.1_postcss@8.4.23
preact: 10.11.3
preact-render-to-string: 5.2.6_preact@10.11.3
- prettier: 2.7.1
+ prettier: 2.8.8
rimraf: 3.0.2
sass: 1.56.1
swr: 2.0.3
@@ -14170,8 +14170,8 @@ packages:
engines: {node: '>=4'}
dev: true
- /prettier/2.7.1:
- resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==}
+ /prettier/2.8.8:
+ resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
engines: {node: '>=10.13.0'}
hasBin: true
dev: true