summaryrefslogtreecommitdiff
path: root/packages/taler-util/src/transactions-types.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-util/src/transactions-types.ts')
-rw-r--r--packages/taler-util/src/transactions-types.ts385
1 files changed, 305 insertions, 80 deletions
diff --git a/packages/taler-util/src/transactions-types.ts b/packages/taler-util/src/transactions-types.ts
index 62caaa055..cee3de9fa 100644
--- a/packages/taler-util/src/transactions-types.ts
+++ b/packages/taler-util/src/transactions-types.ts
@@ -24,41 +24,143 @@
/**
* Imports.
*/
-import { TalerProtocolTimestamp } from "./time.js";
+import {
+ Codec,
+ buildCodecForObject,
+ codecForAny,
+ codecForBoolean,
+ codecForConstString,
+ codecForEither,
+ codecForList,
+ codecForString,
+ codecOptional,
+} from "./codec.js";
import {
AmountString,
- Product,
InternationalizedString,
MerchantInfo,
codecForInternationalizedString,
codecForMerchantInfo,
- codecForProduct,
- Location,
} from "./taler-types.js";
-import {
- Codec,
- buildCodecForObject,
- codecOptional,
- codecForString,
- codecForList,
- codecForAny,
-} from "./codec.js";
+import { TalerPreciseTimestamp, TalerProtocolTimestamp } from "./time.js";
import {
RefreshReason,
+ ScopeInfo,
TalerErrorDetail,
TransactionIdStr,
+ TransactionStateFilter,
+ WithdrawalExchangeAccountDetails,
+ codecForScopeInfo,
} from "./wallet-types.js";
export interface TransactionsRequest {
/**
* return only transactions in the given currency
+ *
+ * it will be removed in next release
+ *
+ * @deprecated use scopeInfo
*/
currency?: string;
/**
+ * return only transactions in the given scopeInfo
+ */
+ scopeInfo?: ScopeInfo;
+
+ /**
* if present, results will be limited to transactions related to the given search string
*/
search?: string;
+
+ /**
+ * Sort order of the transaction items.
+ * By default, items are sorted ascending by their
+ * main timestamp.
+ *
+ * ascending: ascending by timestamp, but pending transactions first
+ * descending: ascending by timestamp, but pending transactions first
+ * stable-ascending: ascending by timestamp, with pending transactions amidst other transactions
+ * (stable in the sense of: pending transactions don't jump around)
+ */
+ sort?: "ascending" | "descending" | "stable-ascending";
+
+ /**
+ * If true, include all refreshes in the transactions list.
+ */
+ includeRefreshes?: boolean;
+
+ filterByState?: TransactionStateFilter;
+}
+
+export interface TransactionState {
+ major: TransactionMajorState;
+ minor?: TransactionMinorState;
+}
+
+export enum TransactionMajorState {
+ // No state, only used when reporting transitions into the initial state
+ None = "none",
+ Pending = "pending",
+ Done = "done",
+ Aborting = "aborting",
+ Aborted = "aborted",
+ Suspended = "suspended",
+ Dialog = "dialog",
+ SuspendedAborting = "suspended-aborting",
+ Failed = "failed",
+ Expired = "expired",
+ // Only used for the notification, never in the transaction history
+ Deleted = "deleted",
+}
+
+export enum TransactionMinorState {
+ // Placeholder until D37 is fully implemented
+ Unknown = "unknown",
+ Deposit = "deposit",
+ KycRequired = "kyc",
+ AmlRequired = "aml",
+ MergeKycRequired = "merge-kyc",
+ Track = "track",
+ SubmitPayment = "submit-payment",
+ RebindSession = "rebind-session",
+ Refresh = "refresh",
+ Pickup = "pickup",
+ AutoRefund = "auto-refund",
+ User = "user",
+ Bank = "bank",
+ Exchange = "exchange",
+ ClaimProposal = "claim-proposal",
+ CheckRefund = "check-refund",
+ CreatePurse = "create-purse",
+ DeletePurse = "delete-purse",
+ RefreshExpired = "refresh-expired",
+ Ready = "ready",
+ Merge = "merge",
+ Repurchase = "repurchase",
+ BankRegisterReserve = "bank-register-reserve",
+ BankConfirmTransfer = "bank-confirm-transfer",
+ WithdrawCoins = "withdraw-coins",
+ ExchangeWaitReserve = "exchange-wait-reserve",
+ AbortingBank = "aborting-bank",
+ Aborting = "aborting",
+ Refused = "refused",
+ Withdraw = "withdraw",
+ MerchantOrderProposed = "merchant-order-proposed",
+ Proposed = "proposed",
+ RefundAvailable = "refund-available",
+ AcceptRefund = "accept-refund",
+ PaidByOther = "paid-by-other",
+ CompletedByOtherWallet = "completed-by-other-wallet",
+}
+
+export enum TransactionAction {
+ Delete = "delete",
+ Suspend = "suspend",
+ Resume = "resume",
+ Abort = "abort",
+ Fail = "fail",
+ Retry = "retry",
}
export interface TransactionsResponse {
@@ -78,18 +180,17 @@ export interface TransactionCommon {
type: TransactionType;
// main timestamp of the transaction
- timestamp: TalerProtocolTimestamp;
+ timestamp: TalerPreciseTimestamp;
- // true if the transaction is still pending, false otherwise
- // If a transaction is not longer pending, its timestamp will be updated,
- // but its transactionId will remain unchanged
- pending: boolean;
+ /**
+ * Transaction state, as per DD37.
+ */
+ txState: TransactionState;
/**
- * True if the transaction encountered a problem that might be
- * permanent. A frozen transaction won't be automatically retried.
+ * Possible transitions based on the current state.
*/
- frozen: boolean;
+ txActions: TransactionAction[];
/**
* Raw amount of the transaction (exclusive of fees or other extra costs).
@@ -102,31 +203,41 @@ export interface TransactionCommon {
amountEffective: AmountString;
error?: TalerErrorDetail;
+
+ /**
+ * If the transaction minor state is in KycRequired this field is going to
+ * have the location where the user need to go to complete KYC information.
+ */
+ kycUrl?: string;
}
export type Transaction =
| TransactionWithdrawal
| TransactionPayment
| TransactionRefund
- | TransactionTip
| TransactionRefresh
| TransactionDeposit
| TransactionPeerPullCredit
| TransactionPeerPullDebit
| TransactionPeerPushCredit
- | TransactionPeerPushDebit;
+ | TransactionPeerPushDebit
+ | TransactionInternalWithdrawal
+ | TransactionRecoup
+ | TransactionDenomLoss;
export enum TransactionType {
Withdrawal = "withdrawal",
+ InternalWithdrawal = "internal-withdrawal",
Payment = "payment",
Refund = "refund",
Refresh = "refresh",
- Tip = "tip",
Deposit = "deposit",
PeerPushDebit = "peer-push-debit",
PeerPushCredit = "peer-push-credit",
PeerPullDebit = "peer-pull-debit",
PeerPullCredit = "peer-pull-credit",
+ Recoup = "recoup",
+ DenomLoss = "denom-loss",
}
export enum WithdrawalType {
@@ -145,11 +256,20 @@ interface WithdrawalDetailsForManualTransfer {
* Payto URIs that the exchange supports.
*
* Already contains the amount and message.
+ *
+ * @deprecated in favor of exchangeCreditAccounts
*/
exchangePaytoUris: string[];
+ exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];
+
// Public key of the reserve
reservePub: string;
+
+ /**
+ * Is the reserve ready for withdrawal?
+ */
+ reserveIsReady: boolean;
}
interface WithdrawalDetailsForTalerBankIntegrationApi {
@@ -170,10 +290,34 @@ interface WithdrawalDetailsForTalerBankIntegrationApi {
// Public key of the reserve
reservePub: string;
+
+ /**
+ * Is the reserve ready for withdrawal?
+ */
+ reserveIsReady: boolean;
+
+ exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];
+}
+
+export enum DenomLossEventType {
+ DenomExpired = "denom-expired",
+ DenomVanished = "denom-vanished",
+ DenomUnoffered = "denom-unoffered",
+}
+
+/**
+ * A transaction to indicate financial loss due to denominations
+ * that became unusable for deposits.
+ */
+export interface TransactionDenomLoss extends TransactionCommon {
+ type: TransactionType.DenomLoss;
+ lossEventType: DenomLossEventType;
+ exchangeBaseUrl: string;
}
-// This should only be used for actual withdrawals
-// and not for tips that have their own transactions type.
+/**
+ * A withdrawal transaction (either bank-integrated or manual).
+ */
export interface TransactionWithdrawal extends TransactionCommon {
type: TransactionType.Withdrawal;
@@ -195,6 +339,40 @@ export interface TransactionWithdrawal extends TransactionCommon {
withdrawalDetails: WithdrawalDetails;
}
+/**
+ * Internal withdrawal operation, only reported on request.
+ *
+ * Some transactions (peer-*-credit) internally do a withdrawal,
+ * but only the peer-*-credit transaction is reported.
+ *
+ * The internal withdrawal transaction allows to access the details of
+ * the underlying withdrawal for testing/debugging.
+ *
+ * It is usually not reported, so that amounts of transactions properly
+ * add up, since the amountEffecive of the withdrawal is already reported
+ * in the peer-*-credit transaction.
+ */
+export interface TransactionInternalWithdrawal extends TransactionCommon {
+ type: TransactionType.InternalWithdrawal;
+
+ /**
+ * Exchange of the withdrawal.
+ */
+ exchangeBaseUrl: string;
+
+ /**
+ * Amount that got subtracted from the reserve balance.
+ */
+ amountRaw: AmountString;
+
+ /**
+ * Amount that actually was (or will be) added to the wallet's balance.
+ */
+ amountEffective: AmountString;
+
+ withdrawalDetails: WithdrawalDetails;
+}
+
export interface PeerInfoShort {
expiration: TalerProtocolTimestamp | undefined;
summary: string | undefined;
@@ -224,8 +402,10 @@ export interface TransactionPeerPullCredit extends TransactionCommon {
/**
* URI to send to the other party.
+ *
+ * Only available in the right state.
*/
- talerUri: string;
+ talerUri: string | undefined;
}
/**
@@ -269,8 +449,11 @@ export interface TransactionPeerPushDebit extends TransactionCommon {
/**
* URI to accept the payment.
+ *
+ * Only present if the transaction is in a state where the other party can
+ * accept the payment.
*/
- talerUri: string;
+ talerUri?: string;
}
/**
@@ -296,6 +479,13 @@ export interface TransactionPeerPushCredit extends TransactionCommon {
amountEffective: AmountString;
}
+/**
+ * The exchange revoked a key and the wallet recoups funds.
+ */
+export interface TransactionRecoup extends TransactionCommon {
+ type: TransactionType.Recoup;
+}
+
export enum PaymentStatus {
/**
* Explicitly aborted after timeout / failure
@@ -333,11 +523,6 @@ export interface TransactionPayment extends TransactionCommon {
proposalId: string;
/**
- * How far did the wallet get with processing the payment?
- */
- status: PaymentStatus;
-
- /**
* Amount that must be paid for the contract
*/
amountRaw: AmountString;
@@ -366,6 +551,16 @@ export interface TransactionPayment extends TransactionCommon {
* Reference to applied refunds
*/
refunds: RefundInfoShort[];
+
+ /**
+ * Is the wallet currently checking for a refund?
+ */
+ refundQueryActive: boolean;
+
+ /**
+ * Does this purchase has an pos validation
+ */
+ posConfirmation: string | undefined;
}
export interface OrderShortInfo {
@@ -395,22 +590,6 @@ export interface OrderShortInfo {
summary_i18n?: InternationalizedString;
/**
- * List of products that are part of the order
- */
- products: Product[] | undefined;
-
- /**
- * Time indicating when the order should be delivered.
- * May be overwritten by individual products.
- */
- delivery_date?: TalerProtocolTimestamp;
-
- /**
- * Delivery location for (all!) products.
- */
- delivery_location?: Location;
-
- /**
* URL of the fulfillment, given by the merchant
*/
fulfillmentUrl?: string;
@@ -434,42 +613,31 @@ export interface RefundInfoShort {
amountRaw: AmountString;
}
-export interface TransactionRefund extends TransactionCommon {
- type: TransactionType.Refund;
-
- // ID for the transaction that is refunded
- refundedTransactionId: string;
-
- // Additional information about the refunded payment
- info: OrderShortInfo;
-
+/**
+ * Summary information about the payment that we got a refund for.
+ */
+export interface RefundPaymentInfo {
+ summary: string;
+ summary_i18n?: InternationalizedString;
/**
- * Amount pending to be picked up
+ * More information about the merchant
*/
- refundPending: AmountString | undefined;
+ merchant: MerchantInfo;
+}
+
+export interface TransactionRefund extends TransactionCommon {
+ type: TransactionType.Refund;
// Amount that has been refunded by the merchant
amountRaw: AmountString;
// Amount will be added to the wallet's balance after fees and refreshing
amountEffective: AmountString;
-}
-export interface TransactionTip extends TransactionCommon {
- type: TransactionType.Tip;
-
- // Raw amount of the tip, without extra fees that apply
- amountRaw: AmountString;
-
- /**
- * More information about the merchant
- */
- // merchant: MerchantInfo;
-
- // Amount will be (or was) added to the wallet's balance after fees and refreshing
- amountEffective: AmountString;
+ // ID for the transaction that is refunded
+ refundedTransactionId: string;
- merchantBaseUrl: string;
+ paymentInfo: RefundPaymentInfo | undefined;
}
/**
@@ -480,11 +648,6 @@ export interface TransactionTip extends TransactionCommon {
export interface TransactionRefresh extends TransactionCommon {
type: TransactionType.Refresh;
- /**
- * Exchange that the coins are refreshed with
- */
- exchangeBaseUrl: string;
-
refreshReason: RefreshReason;
/**
@@ -500,8 +663,26 @@ export interface TransactionRefresh extends TransactionCommon {
/**
* Fees, i.e. the effective, negative effect of the refresh
* on the balance.
+ *
+ * Only applicable for stand-alone refreshes, and zero for
+ * other refreshes where the transaction itself accounts for the
+ * refresh fee.
*/
amountEffective: AmountString;
+
+ refreshInputAmount: AmountString;
+ refreshOutputAmount: AmountString;
+}
+
+export interface DepositTransactionTrackingState {
+ // Raw wire transfer identifier of the deposit.
+ wireTransferId: string;
+ // When was the wire transfer given to the bank.
+ timestampExecuted: TalerProtocolTimestamp;
+ // Total amount transfer for this wtid (including fees)
+ amountRaw: AmountString;
+ // Wire fee amount for this exchange
+ wireFee: AmountString;
}
/**
@@ -529,6 +710,15 @@ export interface TransactionDeposit extends TransactionCommon {
amountEffective: AmountString;
wireTransferDeadline: TalerProtocolTimestamp;
+
+ wireTransferProgress: number;
+
+ /**
+ * Did all the deposit requests succeed?
+ */
+ deposited: boolean;
+
+ trackingState: Array<DepositTransactionTrackingState>;
}
export interface TransactionByIdRequest {
@@ -541,10 +731,32 @@ export const codecForTransactionByIdRequest =
.property("transactionId", codecForString())
.build("TransactionByIdRequest");
+export interface WithdrawalTransactionByURIRequest {
+ talerWithdrawUri: string;
+}
+
+export const codecForWithdrawalTransactionByURIRequest =
+ (): Codec<WithdrawalTransactionByURIRequest> =>
+ buildCodecForObject<WithdrawalTransactionByURIRequest>()
+ .property("talerWithdrawUri", codecForString())
+ .build("WithdrawalTransactionByURIRequest");
+
export const codecForTransactionsRequest = (): Codec<TransactionsRequest> =>
buildCodecForObject<TransactionsRequest>()
.property("currency", codecOptional(codecForString()))
+ .property("scopeInfo", codecOptional(codecForScopeInfo()))
.property("search", codecOptional(codecForString()))
+ .property(
+ "sort",
+ codecOptional(
+ codecForEither(
+ codecForConstString("ascending"),
+ codecForConstString("descending"),
+ codecForConstString("stable-ascending"),
+ ),
+ ),
+ )
+ .property("includeRefreshes", codecOptional(codecForBoolean()))
.build("TransactionsRequest");
// FIXME: do full validation here!
@@ -564,7 +776,20 @@ export const codecForOrderShortInfo = (): Codec<OrderShortInfo> =>
.property("fulfillmentUrl", codecOptional(codecForString()))
.property("merchant", codecForMerchantInfo())
.property("orderId", codecForString())
- .property("products", codecOptional(codecForList(codecForProduct())))
.property("summary", codecForString())
.property("summary_i18n", codecOptional(codecForInternationalizedString()))
.build("OrderShortInfo");
+
+export interface ListAssociatedRefreshesRequest {
+ transactionId: string;
+}
+
+export const codecForListAssociatedRefreshesRequest =
+ (): Codec<ListAssociatedRefreshesRequest> =>
+ buildCodecForObject<ListAssociatedRefreshesRequest>()
+ .property("transactionId", codecForString())
+ .build("ListAssociatedRefreshesRequest");
+
+export interface ListAssociatedRefreshesResponse {
+ transactionIds: string[];
+}