diff options
Diffstat (limited to 'packages/taler-util/src/transactions-types.ts')
-rw-r--r-- | packages/taler-util/src/transactions-types.ts | 385 |
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[]; +} |