/*
This file is part of GNU Taler
(C) 2015-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
*/
/**
* Types used by clients of the wallet.
*
* These types are defined in a separate file make tree shaking easier, since
* some components use these types (via RPC) but do not depend on the wallet
* code directly.
*
* @author Florian Dold
*/
/**
* Imports.
*/
import { AmountJson, codecForAmountString } from "./amounts.js";
import { BackupRecovery } from "./backup-types.js";
import {
Codec,
Context,
DecodingError,
buildCodecForObject,
buildCodecForUnion,
codecForAny,
codecForBoolean,
codecForConstString,
codecForEither,
codecForList,
codecForMap,
codecForNumber,
codecForString,
codecOptional,
renderContext,
} from "./codec.js";
import { CurrencySpecification } from "./index.js";
import { VersionMatchResult } from "./libtool-version.js";
import { PaytoUri } from "./payto.js";
import { AgeCommitmentProof } from "./taler-crypto.js";
import { TalerErrorCode } from "./taler-error-codes.js";
import {
AccountRestriction,
AmountString,
AuditorDenomSig,
CoinEnvelope,
DenomKeyType,
DenominationPubKey,
ExchangeAuditor,
ExchangeWireAccount,
InternationalizedString,
MerchantContractTerms,
MerchantInfo,
PeerContractTerms,
UnblindedSignature,
codecForExchangeWireAccount,
codecForMerchantContractTerms,
codecForPeerContractTerms,
} from "./taler-types.js";
import {
AbsoluteTime,
TalerPreciseTimestamp,
TalerProtocolDuration,
TalerProtocolTimestamp,
codecForAbsoluteTime,
codecForTimestamp,
} from "./time.js";
import {
OrderShortInfo,
TransactionState,
TransactionType,
} from "./transactions-types.js";
/**
* Identifier for a transaction in the wallet.
*/
declare const __txId: unique symbol;
export type TransactionIdStr = `txn:${string}:${string}` & { [__txId]: true };
/**
* Identifier for a pending task in the wallet.
*/
declare const __pndId: unique symbol;
export type PendingIdStr = `pnd:${string}:${string}` & { [__pndId]: true };
declare const __tmbId: unique symbol;
export type TombstoneIdStr = `tmb:${string}:${string}` & { [__tmbId]: true };
function codecForTransactionIdStr(): Codec {
return {
decode(x: any, c?: Context): TransactionIdStr {
if (typeof x === "string" && x.startsWith("txn:")) {
return x as TransactionIdStr;
}
throw new DecodingError(
`expected string starting with "txn:" at ${renderContext(
c,
)} but got ${x}`,
);
},
};
}
function codecForPendingIdStr(): Codec {
return {
decode(x: any, c?: Context): PendingIdStr {
if (typeof x === "string" && x.startsWith("txn:")) {
return x as PendingIdStr;
}
throw new DecodingError(
`expected string starting with "txn:" at ${renderContext(
c,
)} but got ${x}`,
);
},
};
}
function codecForTombstoneIdStr(): Codec {
return {
decode(x: any, c?: Context): TombstoneIdStr {
if (typeof x === "string" && x.startsWith("tmb:")) {
return x as TombstoneIdStr;
}
throw new DecodingError(
`expected string starting with "tmb:" at ${renderContext(
c,
)} but got ${x}`,
);
},
};
}
/**
* Response for the create reserve request to the wallet.
*/
export class CreateReserveResponse {
/**
* Exchange URL where the bank should create the reserve.
* The URL is canonicalized in the response.
*/
exchange: string;
/**
* Reserve public key of the newly created reserve.
*/
reservePub: string;
}
export interface GetBalanceDetailRequest {
currency: string;
}
export const codecForGetBalanceDetailRequest =
(): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.build("GetBalanceDetailRequest");
/**
* How the amount should be interpreted in a transaction
* Effective = how the balance is change
* Raw = effective amount without fee
*
* Depending on the transaction, raw can be higher than effective
*/
export enum TransactionAmountMode {
Effective = "effective",
Raw = "raw",
}
export type GetPlanForOperationRequest =
| GetPlanForWithdrawRequest
| GetPlanForDepositRequest;
// | GetPlanForPushDebitRequest
// | GetPlanForPullCreditRequest
// | GetPlanForPaymentRequest
// | GetPlanForTipRequest
// | GetPlanForRefundRequest
// | GetPlanForPullDebitRequest
// | GetPlanForPushCreditRequest;
interface GetPlanForWalletInitiatedOperation {
instructedAmount: AmountString;
mode: TransactionAmountMode;
}
export interface ConvertAmountRequest {
amount: AmountString;
type: TransactionAmountMode;
}
export const codecForConvertAmountRequest =
buildCodecForObject()
.property("amount", codecForAmountString())
.property(
"type",
codecForEither(
codecForConstString(TransactionAmountMode.Raw),
codecForConstString(TransactionAmountMode.Effective),
),
)
.build("ConvertAmountRequest");
export interface GetAmountRequest {
currency: string;
}
export const codecForGetAmountRequest = buildCodecForObject()
.property("currency", codecForString())
.build("GetAmountRequest");
interface GetPlanToCompleteOperation {
instructedAmount: AmountString;
}
const codecForGetPlanForWalletInitiatedOperation = <
T extends GetPlanForWalletInitiatedOperation,
>() =>
buildCodecForObject()
.property(
"mode",
codecForEither(
codecForConstString(TransactionAmountMode.Raw),
codecForConstString(TransactionAmountMode.Effective),
),
)
.property("instructedAmount", codecForAmountString());
interface GetPlanForWithdrawRequest extends GetPlanForWalletInitiatedOperation {
type: TransactionType.Withdrawal;
exchangeUrl?: string;
}
interface GetPlanForDepositRequest extends GetPlanForWalletInitiatedOperation {
type: TransactionType.Deposit;
account: string; //payto string
}
interface GetPlanForPushDebitRequest
extends GetPlanForWalletInitiatedOperation {
type: TransactionType.PeerPushDebit;
}
interface GetPlanForPullCreditRequest
extends GetPlanForWalletInitiatedOperation {
type: TransactionType.PeerPullCredit;
exchangeUrl: string;
}
const codecForGetPlanForWithdrawRequest =
codecForGetPlanForWalletInitiatedOperation()
.property("type", codecForConstString(TransactionType.Withdrawal))
.property("exchangeUrl", codecOptional(codecForString()))
.build("GetPlanForWithdrawRequest");
const codecForGetPlanForDepositRequest =
codecForGetPlanForWalletInitiatedOperation()
.property("type", codecForConstString(TransactionType.Deposit))
.property("account", codecForString())
.build("GetPlanForDepositRequest");
const codecForGetPlanForPushDebitRequest =
codecForGetPlanForWalletInitiatedOperation()
.property("type", codecForConstString(TransactionType.PeerPushDebit))
.build("GetPlanForPushDebitRequest");
const codecForGetPlanForPullCreditRequest =
codecForGetPlanForWalletInitiatedOperation()
.property("type", codecForConstString(TransactionType.PeerPullCredit))
.property("exchangeUrl", codecForString())
.build("GetPlanForPullCreditRequest");
interface GetPlanForPaymentRequest extends GetPlanToCompleteOperation {
type: TransactionType.Payment;
wireMethod: string;
ageRestriction: number;
maxDepositFee: AmountString;
maxWireFee: AmountString;
}
// interface GetPlanForTipRequest extends GetPlanForOperationBase {
// type: TransactionType.Tip;
// }
// interface GetPlanForRefundRequest extends GetPlanForOperationBase {
// type: TransactionType.Refund;
// }
interface GetPlanForPullDebitRequest extends GetPlanToCompleteOperation {
type: TransactionType.PeerPullDebit;
}
interface GetPlanForPushCreditRequest extends GetPlanToCompleteOperation {
type: TransactionType.PeerPushCredit;
}
const codecForGetPlanForPaymentRequest =
buildCodecForObject()
.property("type", codecForConstString(TransactionType.Payment))
.property("maxDepositFee", codecForAmountString())
.property("maxWireFee", codecForAmountString())
.build("GetPlanForPaymentRequest");
const codecForGetPlanForPullDebitRequest =
buildCodecForObject()
.property("type", codecForConstString(TransactionType.PeerPullDebit))
.build("GetPlanForPullDebitRequest");
const codecForGetPlanForPushCreditRequest =
buildCodecForObject()
.property("type", codecForConstString(TransactionType.PeerPushCredit))
.build("GetPlanForPushCreditRequest");
export const codecForGetPlanForOperationRequest =
(): Codec =>
buildCodecForUnion()
.discriminateOn("type")
.alternative(
TransactionType.Withdrawal,
codecForGetPlanForWithdrawRequest,
)
.alternative(TransactionType.Deposit, codecForGetPlanForDepositRequest)
// .alternative(
// TransactionType.PeerPushDebit,
// codecForGetPlanForPushDebitRequest,
// )
// .alternative(
// TransactionType.PeerPullCredit,
// codecForGetPlanForPullCreditRequest,
// )
// .alternative(TransactionType.Payment, codecForGetPlanForPaymentRequest)
// .alternative(
// TransactionType.PeerPullDebit,
// codecForGetPlanForPullDebitRequest,
// )
// .alternative(
// TransactionType.PeerPushCredit,
// codecForGetPlanForPushCreditRequest,
// )
.build("GetPlanForOperationRequest");
export interface GetPlanForOperationResponse {
effectiveAmount: AmountString;
rawAmount: AmountString;
counterPartyAmount?: AmountString;
details: any;
}
export const codecForGetPlanForOperationResponse =
(): Codec =>
buildCodecForObject()
.property("effectiveAmount", codecForAmountString())
.property("rawAmount", codecForAmountString())
.property("details", codecForAny())
.property("counterPartyAmount", codecOptional(codecForAmountString()))
.build("GetPlanForOperationResponse");
export interface AmountResponse {
effectiveAmount: AmountString;
rawAmount: AmountString;
}
export const codecForAmountResponse = (): Codec =>
buildCodecForObject()
.property("effectiveAmount", codecForAmountString())
.property("rawAmount", codecForAmountString())
.build("AmountResponse");
export enum BalanceFlag {
IncomingKyc = "incoming-kyc",
IncomingAml = "incoming-aml",
IncomingConfirmation = "incoming-confirmation",
OutgoingKyc = "outgoing-kyc",
}
export interface WalletBalance {
scopeInfo: ScopeInfo;
available: AmountString;
pendingIncoming: AmountString;
pendingOutgoing: AmountString;
/**
* Does the balance for this currency have a pending
* transaction?
*
* @deprecated use flags and pendingIncoming/pendingOutgoing instead
*/
hasPendingTransactions: boolean;
/**
* Is there a transaction that requires user input?
*
* @deprecated use flags instead
*/
requiresUserInput: boolean;
flags: BalanceFlag[];
}
export const codecForScopeInfoGlobal = (): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.property("type", codecForConstString(ScopeType.Global))
.build("ScopeInfoGlobal");
export const codecForScopeInfoExchange = (): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.property("type", codecForConstString(ScopeType.Exchange))
.property("url", codecForString())
.build("ScopeInfoExchange");
export const codecForScopeInfoAuditor = (): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.property("type", codecForConstString(ScopeType.Auditor))
.property("url", codecForString())
.build("ScopeInfoAuditor");
export const codecForScopeInfo = (): Codec =>
buildCodecForUnion()
.discriminateOn("type")
.alternative(ScopeType.Global, codecForScopeInfoGlobal())
.alternative(ScopeType.Exchange, codecForScopeInfoExchange())
.alternative(ScopeType.Auditor, codecForScopeInfoAuditor())
.build("ScopeInfo");
export interface GetCurrencySpecificationRequest {
scope: ScopeInfo;
}
export const codecForGetCurrencyInfoRequest =
(): Codec =>
buildCodecForObject()
.property("scope", codecForScopeInfo())
.build("GetCurrencySpecificationRequest");
export interface ListExchangesForScopedCurrencyRequest {
scope: ScopeInfo;
}
export const codecForListExchangesForScopedCurrencyRequest =
(): Codec =>
buildCodecForObject()
.property("scope", codecForScopeInfo())
.build("ListExchangesForScopedCurrencyRequest");
export interface GetCurrencySpecificationResponse {
currencySpecification: CurrencySpecification;
}
export interface InitRequest {
skipDefaults?: boolean;
}
export interface InitResponse {
versionInfo: WalletCoreVersion;
}
export enum ScopeType {
Global = "global",
Exchange = "exchange",
Auditor = "auditor",
}
export type ScopeInfoGlobal = { type: ScopeType.Global; currency: string };
export type ScopeInfoExchange = {
type: ScopeType.Exchange;
currency: string;
url: string;
};
export type ScopeInfoAuditor = {
type: ScopeType.Auditor;
currency: string;
url: string;
};
export type ScopeInfo = ScopeInfoGlobal | ScopeInfoExchange | ScopeInfoAuditor;
export interface BalancesResponse {
balances: WalletBalance[];
}
export const codecForBalance = (): Codec =>
buildCodecForObject()
.property("scopeInfo", codecForAny()) // FIXME
.property("available", codecForAmountString())
.property("hasPendingTransactions", codecForBoolean())
.property("pendingIncoming", codecForAmountString())
.property("pendingOutgoing", codecForAmountString())
.property("requiresUserInput", codecForBoolean())
.property("flags", codecForAny()) // FIXME
.build("Balance");
export const codecForBalancesResponse = (): Codec =>
buildCodecForObject()
.property("balances", codecForList(codecForBalance()))
.build("BalancesResponse");
/**
* For terseness.
*/
export function mkAmount(
value: number,
fraction: number,
currency: string,
): AmountJson {
return { value, fraction, currency };
}
/**
* Status of a coin.
*/
export enum CoinStatus {
/**
* Withdrawn and never shown to anybody.
*/
Fresh = "fresh",
/**
* Fresh, but currently marked as "suspended", thus won't be used
* for spending. Used for testing.
*/
FreshSuspended = "fresh-suspended",
/**
* A coin that has been spent and refreshed.
*/
Dormant = "dormant",
}
/**
* Easy to process format for the public data of coins
* managed by the wallet.
*/
export interface CoinDumpJson {
coins: Array<{
/**
* The coin's denomination's public key.
*/
denom_pub: DenominationPubKey;
/**
* Hash of denom_pub.
*/
denom_pub_hash: string;
/**
* Value of the denomination (without any fees).
*/
denom_value: string;
/**
* Public key of the coin.
*/
coin_pub: string;
/**
* Base URL of the exchange for the coin.
*/
exchange_base_url: string;
/**
* Public key of the parent coin.
* Only present if this coin was obtained via refreshing.
*/
refresh_parent_coin_pub: string | undefined;
/**
* Public key of the reserve for this coin.
* Only present if this coin was obtained via refreshing.
*/
withdrawal_reserve_pub: string | undefined;
coin_status: CoinStatus;
spend_allocation:
| {
id: string;
amount: AmountString;
}
| undefined;
/**
* Information about the age restriction
*/
ageCommitmentProof: AgeCommitmentProof | undefined;
}>;
}
export enum ConfirmPayResultType {
Done = "done",
Pending = "pending",
}
/**
* Result for confirmPay
*/
export interface ConfirmPayResultDone {
type: ConfirmPayResultType.Done;
contractTerms: MerchantContractTerms;
transactionId: TransactionIdStr;
}
export interface ConfirmPayResultPending {
type: ConfirmPayResultType.Pending;
transactionId: TransactionIdStr;
lastError: TalerErrorDetail | undefined;
}
export const codecForTalerErrorDetail = (): Codec =>
buildCodecForObject()
.property("code", codecForNumber())
.property("when", codecOptional(codecForAbsoluteTime))
.property("hint", codecOptional(codecForString()))
.build("TalerErrorDetail");
export type ConfirmPayResult = ConfirmPayResultDone | ConfirmPayResultPending;
export const codecForConfirmPayResultPending =
(): Codec =>
buildCodecForObject()
.property("lastError", codecOptional(codecForTalerErrorDetail()))
.property("transactionId", codecForTransactionIdStr())
.property("type", codecForConstString(ConfirmPayResultType.Pending))
.build("ConfirmPayResultPending");
export const codecForConfirmPayResultDone = (): Codec =>
buildCodecForObject()
.property("type", codecForConstString(ConfirmPayResultType.Done))
.property("transactionId", codecForTransactionIdStr())
.property("contractTerms", codecForMerchantContractTerms())
.build("ConfirmPayResultDone");
export const codecForConfirmPayResult = (): Codec =>
buildCodecForUnion()
.discriminateOn("type")
.alternative(
ConfirmPayResultType.Pending,
codecForConfirmPayResultPending(),
)
.alternative(ConfirmPayResultType.Done, codecForConfirmPayResultDone())
.build("ConfirmPayResult");
/**
* Information about all sender wire details known to the wallet,
* as well as exchanges that accept these wire types.
*/
export interface SenderWireInfos {
/**
* Mapping from exchange base url to list of accepted
* wire types.
*/
exchangeWireTypes: { [exchangeBaseUrl: string]: string[] };
/**
* Sender wire information stored in the wallet.
*/
senderWires: string[];
}
/**
* Request to mark a reserve as confirmed.
*/
export interface ConfirmReserveRequest {
/**
* Public key of then reserve that should be marked
* as confirmed.
*/
reservePub: string;
}
export const codecForConfirmReserveRequest = (): Codec =>
buildCodecForObject()
.property("reservePub", codecForString())
.build("ConfirmReserveRequest");
export interface PrepareRefundResult {
proposalId: string;
effectivePaid: AmountString;
gone: AmountString;
granted: AmountString;
pending: boolean;
awaiting: AmountString;
info: OrderShortInfo;
}
export interface PrepareTipResult {
/**
* Unique ID for the tip assigned by the wallet.
* Typically different from the merchant-generated tip ID.
*
* @deprecated use transactionId instead
*/
walletRewardId: string;
/**
* Tip transaction ID.
*/
transactionId: string;
/**
* Has the tip already been accepted?
*/
accepted: boolean;
/**
* Amount that the merchant gave.
*/
rewardAmountRaw: AmountString;
/**
* Amount that arrived at the wallet.
* Might be lower than the raw amount due to fees.
*/
rewardAmountEffective: AmountString;
/**
* Base URL of the merchant backend giving then tip.
*/
merchantBaseUrl: string;
/**
* Base URL of the exchange that is used to withdraw the tip.
* Determined by the merchant, the wallet/user has no choice here.
*/
exchangeBaseUrl: string;
/**
* Time when the tip will expire. After it expired, it can't be picked
* up anymore.
*/
expirationTimestamp: TalerProtocolTimestamp;
}
export interface AcceptTipResponse {
transactionId: TransactionIdStr;
next_url?: string;
}
export const codecForPrepareTipResult = (): Codec =>
buildCodecForObject()
.property("accepted", codecForBoolean())
.property("rewardAmountRaw", codecForAmountString())
.property("rewardAmountEffective", codecForAmountString())
.property("exchangeBaseUrl", codecForString())
.property("merchantBaseUrl", codecForString())
.property("expirationTimestamp", codecForTimestamp)
.property("walletRewardId", codecForString())
.property("transactionId", codecForString())
.build("PrepareRewardResult");
export interface BenchmarkResult {
time: { [s: string]: number };
repetitions: number;
}
export enum PreparePayResultType {
PaymentPossible = "payment-possible",
InsufficientBalance = "insufficient-balance",
AlreadyConfirmed = "already-confirmed",
}
export const codecForPreparePayResultPaymentPossible =
(): Codec =>
buildCodecForObject()
.property("amountEffective", codecForAmountString())
.property("amountRaw", codecForAmountString())
.property("contractTerms", codecForMerchantContractTerms())
.property("transactionId", codecForTransactionIdStr())
.property("proposalId", codecForString())
.property("contractTermsHash", codecForString())
.property("talerUri", codecForString())
.property(
"status",
codecForConstString(PreparePayResultType.PaymentPossible),
)
.build("PreparePayResultPaymentPossible");
/**
* Detailed reason for why the wallet's balance is insufficient.
*/
export interface PayMerchantInsufficientBalanceDetails {
/**
* Amount requested by the merchant.
*/
amountRequested: AmountString;
/**
* Balance of type "available" (see balance.ts for definition).
*/
balanceAvailable: AmountString;
/**
* Balance of type "material" (see balance.ts for definition).
*/
balanceMaterial: AmountString;
/**
* Balance of type "age-acceptable" (see balance.ts for definition).
*/
balanceAgeAcceptable: AmountString;
/**
* Balance of type "merchant-acceptable" (see balance.ts for definition).
*/
balanceMerchantAcceptable: AmountString;
/**
* Balance of type "merchant-depositable" (see balance.ts for definition).
*/
balanceMerchantDepositable: AmountString;
/**
* If the payment would succeed without fees
* (i.e. balanceMerchantDepositable >= amountRequested),
* this field contains an estimate of the amount that would additionally
* be required to cover the fees.
*
* It is not possible to give an exact value here, since it depends
* on the coin selection for the amount that would be additionally withdrawn.
*/
feeGapEstimate: AmountString;
}
export const codecForPayMerchantInsufficientBalanceDetails =
(): Codec =>
buildCodecForObject()
.property("amountRequested", codecForAmountString())
.property("balanceAgeAcceptable", codecForAmountString())
.property("balanceAvailable", codecForAmountString())
.property("balanceMaterial", codecForAmountString())
.property("balanceMerchantAcceptable", codecForAmountString())
.property("balanceMerchantDepositable", codecForAmountString())
.property("feeGapEstimate", codecForAmountString())
.build("PayMerchantInsufficientBalanceDetails");
export const codecForPreparePayResultInsufficientBalance =
(): Codec =>
buildCodecForObject()
.property("amountRaw", codecForAmountString())
.property("contractTerms", codecForAny())
.property("talerUri", codecForString())
.property("proposalId", codecForString())
.property("transactionId", codecForTransactionIdStr())
.property(
"status",
codecForConstString(PreparePayResultType.InsufficientBalance),
)
.property(
"balanceDetails",
codecForPayMerchantInsufficientBalanceDetails(),
)
.build("PreparePayResultInsufficientBalance");
export const codecForPreparePayResultAlreadyConfirmed =
(): Codec =>
buildCodecForObject()
.property(
"status",
codecForConstString(PreparePayResultType.AlreadyConfirmed),
)
.property("amountEffective", codecOptional(codecForAmountString()))
.property("amountRaw", codecForAmountString())
.property("paid", codecForBoolean())
.property("talerUri", codecForString())
.property("contractTerms", codecForAny())
.property("contractTermsHash", codecForString())
.property("transactionId", codecForTransactionIdStr())
.property("proposalId", codecForString())
.build("PreparePayResultAlreadyConfirmed");
export const codecForPreparePayResult = (): Codec =>
buildCodecForUnion()
.discriminateOn("status")
.alternative(
PreparePayResultType.AlreadyConfirmed,
codecForPreparePayResultAlreadyConfirmed(),
)
.alternative(
PreparePayResultType.InsufficientBalance,
codecForPreparePayResultInsufficientBalance(),
)
.alternative(
PreparePayResultType.PaymentPossible,
codecForPreparePayResultPaymentPossible(),
)
.build("PreparePayResult");
/**
* Result of a prepare pay operation.
*/
export type PreparePayResult =
| PreparePayResultInsufficientBalance
| PreparePayResultAlreadyConfirmed
| PreparePayResultPaymentPossible;
/**
* Payment is possible.
*/
export interface PreparePayResultPaymentPossible {
status: PreparePayResultType.PaymentPossible;
transactionId: TransactionIdStr;
/**
* @deprecated use transactionId instead
*/
proposalId: string;
contractTerms: MerchantContractTerms;
contractTermsHash: string;
amountRaw: AmountString;
amountEffective: AmountString;
talerUri: string;
}
export interface PreparePayResultInsufficientBalance {
status: PreparePayResultType.InsufficientBalance;
transactionId: TransactionIdStr;
/**
* @deprecated use transactionId
*/
proposalId: string;
contractTerms: MerchantContractTerms;
amountRaw: AmountString;
talerUri: string;
balanceDetails: PayMerchantInsufficientBalanceDetails;
}
export interface PreparePayResultAlreadyConfirmed {
status: PreparePayResultType.AlreadyConfirmed;
transactionId: TransactionIdStr;
contractTerms: MerchantContractTerms;
paid: boolean;
amountRaw: AmountString;
amountEffective: AmountString | undefined;
contractTermsHash: string;
/**
* @deprecated use transactionId
*/
proposalId: string;
talerUri: string;
}
export interface BankWithdrawDetails {
selectionDone: boolean;
transferDone: boolean;
amount: AmountJson;
senderWire?: string;
suggestedExchange?: string;
confirmTransferUrl?: string;
wireTypes: string[];
}
export interface AcceptWithdrawalResponse {
reservePub: string;
confirmTransferUrl?: string;
transactionId: TransactionIdStr;
}
/**
* Details about a purchase, including refund status.
*/
export interface PurchaseDetails {
contractTerms: Record;
hasRefund: boolean;
totalRefundAmount: AmountJson;
totalRefundAndRefreshFees: AmountJson;
}
export interface WalletDiagnostics {
walletManifestVersion: string;
walletManifestDisplayVersion: string;
errors: string[];
firefoxIdbProblem: boolean;
dbOutdated: boolean;
}
export interface TalerErrorDetail {
code: TalerErrorCode;
when?: AbsoluteTime;
hint?: string;
[x: string]: unknown;
}
/**
* Minimal information needed about a planchet for unblinding a signature.
*
* Can be a withdrawal/tipping/refresh planchet.
*/
export interface PlanchetUnblindInfo {
denomPub: DenominationPubKey;
blindingKey: string;
}
export interface WithdrawalPlanchet {
coinPub: string;
coinPriv: string;
reservePub: string;
denomPubHash: string;
denomPub: DenominationPubKey;
blindingKey: string;
withdrawSig: string;
coinEv: CoinEnvelope;
coinValue: AmountJson;
coinEvHash: string;
ageCommitmentProof?: AgeCommitmentProof;
}
export interface PlanchetCreationRequest {
secretSeed: string;
coinIndex: number;
value: AmountJson;
feeWithdraw: AmountJson;
denomPub: DenominationPubKey;
reservePub: string;
reservePriv: string;
restrictAge?: number;
}
/**
* Reasons for why a coin is being refreshed.
*/
export enum RefreshReason {
Manual = "manual",
PayMerchant = "pay-merchant",
PayDeposit = "pay-deposit",
PayPeerPush = "pay-peer-push",
PayPeerPull = "pay-peer-pull",
Refund = "refund",
AbortPay = "abort-pay",
AbortDeposit = "abort-deposit",
AbortPeerPushDebit = "abort-peer-push-debit",
AbortPeerPullDebit = "abort-peer-pull-debit",
Recoup = "recoup",
BackupRestored = "backup-restored",
Scheduled = "scheduled",
}
/**
* Request to refresh a single coin.
*/
export interface CoinRefreshRequest {
readonly coinPub: string;
readonly amount: AmountString;
}
/**
* Wrapper for refresh group IDs.
*/
export interface RefreshGroupId {
readonly refreshGroupId: string;
}
/**
* Private data required to make a deposit permission.
*/
export interface DepositInfo {
exchangeBaseUrl: string;
contractTermsHash: string;
coinPub: string;
coinPriv: string;
spendAmount: AmountJson;
timestamp: TalerProtocolTimestamp;
refundDeadline: TalerProtocolTimestamp;
merchantPub: string;
feeDeposit: AmountJson;
wireInfoHash: string;
denomKeyType: DenomKeyType;
denomPubHash: string;
denomSig: UnblindedSignature;
requiredMinimumAge?: number;
ageCommitmentProof?: AgeCommitmentProof;
}
export interface ExchangesShortListResponse {
exchanges: ShortExchangeListItem[];
}
export interface ExchangesListResponse {
exchanges: ExchangeListItem[];
}
export interface ExchangeDetailedResponse {
exchange: ExchangeFullDetails;
}
export interface WalletCoreVersion {
/**
* @deprecated
*/
hash: string | undefined;
version: string;
exchange: string;
merchant: string;
bank: string;
/**
* @deprecated will be removed
*/
devMode: boolean;
}
export interface KnownBankAccountsInfo {
uri: PaytoUri;
kyc_completed: boolean;
currency: string;
alias: string;
}
export interface KnownBankAccounts {
accounts: KnownBankAccountsInfo[];
}
/**
* Wire fee for one wire method
*/
export interface WireFee {
/**
* Fee for wire transfers.
*/
wireFee: AmountString;
/**
* Fees to close and refund a reserve.
*/
closingFee: AmountString;
/**
* Start date of the fee.
*/
startStamp: TalerProtocolTimestamp;
/**
* End date of the fee.
*/
endStamp: TalerProtocolTimestamp;
/**
* Signature made by the exchange master key.
*/
sig: string;
}
export type WireFeeMap = { [wireMethod: string]: WireFee[] };
export interface WireInfo {
feesForType: WireFeeMap;
accounts: ExchangeWireAccount[];
}
export interface ExchangeGlobalFees {
startDate: TalerProtocolTimestamp;
endDate: TalerProtocolTimestamp;
historyFee: AmountString;
accountFee: AmountString;
purseFee: AmountString;
historyTimeout: TalerProtocolDuration;
purseTimeout: TalerProtocolDuration;
purseLimit: number;
signature: string;
}
const codecForWireFee = (): Codec =>
buildCodecForObject()
.property("sig", codecForString())
.property("wireFee", codecForAmountString())
.property("closingFee", codecForAmountString())
.property("startStamp", codecForTimestamp)
.property("endStamp", codecForTimestamp)
.build("codecForWireFee");
const codecForWireInfo = (): Codec =>
buildCodecForObject()
.property("feesForType", codecForMap(codecForList(codecForWireFee())))
.property("accounts", codecForList(codecForExchangeWireAccount()))
.build("codecForWireInfo");
export interface DenominationInfo {
/**
* Value of one coin of the denomination.
*/
value: AmountString;
/**
* Hash of the denomination public key.
* Stored in the database for faster lookups.
*/
denomPubHash: string;
denomPub: DenominationPubKey;
/**
* Fee for withdrawing.
*/
feeWithdraw: AmountString;
/**
* Fee for depositing.
*/
feeDeposit: AmountString;
/**
* Fee for refreshing.
*/
feeRefresh: AmountString;
/**
* Fee for refunding.
*/
feeRefund: AmountString;
/**
* Validity start date of the denomination.
*/
stampStart: TalerProtocolTimestamp;
/**
* Date after which the currency can't be withdrawn anymore.
*/
stampExpireWithdraw: TalerProtocolTimestamp;
/**
* Date after the denomination officially doesn't exist anymore.
*/
stampExpireLegal: TalerProtocolTimestamp;
/**
* Data after which coins of this denomination can't be deposited anymore.
*/
stampExpireDeposit: TalerProtocolTimestamp;
exchangeBaseUrl: string;
}
export type DenomOperation = "deposit" | "withdraw" | "refresh" | "refund";
export type DenomOperationMap = { [op in DenomOperation]: T };
export interface FeeDescription {
group: string;
from: AbsoluteTime;
until: AbsoluteTime;
fee?: AmountString;
}
export interface FeeDescriptionPair {
group: string;
from: AbsoluteTime;
until: AbsoluteTime;
left?: AmountString;
right?: AmountString;
}
export interface TimePoint {
id: string;
group: string;
fee: AmountString;
type: "start" | "end";
moment: AbsoluteTime;
denom: T;
}
export interface ExchangeFullDetails {
exchangeBaseUrl: string;
currency: string;
paytoUris: string[];
auditors: ExchangeAuditor[];
wireInfo: WireInfo;
denomFees: DenomOperationMap;
transferFees: Record;
globalFees: FeeDescription[];
}
export enum ExchangeTosStatus {
Pending = "pending",
Proposed = "proposed",
Accepted = "accepted",
}
export enum ExchangeEntryStatus {
Preset = "preset",
Ephemeral = "ephemeral",
Used = "used",
}
export enum ExchangeUpdateStatus {
Initial = "initial",
InitialUpdate = "initial-update",
Suspended = "suspended",
UnavailableUpdate = "unavailable-update",
Ready = "ready",
ReadyUpdate = "ready-update",
}
export interface OperationErrorInfo {
error: TalerErrorDetail;
}
export interface ShortExchangeListItem {
exchangeBaseUrl: string;
}
/**
* Info about an exchange entry in the wallet.
*/
export interface ExchangeListItem {
exchangeBaseUrl: string;
currency: string | undefined;
paytoUris: string[];
tosStatus: ExchangeTosStatus;
exchangeEntryStatus: ExchangeEntryStatus;
exchangeUpdateStatus: ExchangeUpdateStatus;
ageRestrictionOptions: number[];
scopeInfo: ScopeInfo | undefined;
/**
* Information about the last error that occurred when trying
* to update the exchange info.
*/
lastUpdateErrorInfo?: OperationErrorInfo;
}
const codecForAuditorDenomSig = (): Codec =>
buildCodecForObject()
.property("denom_pub_h", codecForString())
.property("auditor_sig", codecForString())
.build("AuditorDenomSig");
const codecForExchangeAuditor = (): Codec =>
buildCodecForObject()
.property("auditor_pub", codecForString())
.property("auditor_url", codecForString())
.property("denomination_keys", codecForList(codecForAuditorDenomSig()))
.build("codecForExchangeAuditor");
export const codecForFeeDescriptionPair = (): Codec =>
buildCodecForObject()
.property("group", codecForString())
.property("from", codecForAbsoluteTime)
.property("until", codecForAbsoluteTime)
.property("left", codecOptional(codecForAmountString()))
.property("right", codecOptional(codecForAmountString()))
.build("FeeDescriptionPair");
export const codecForFeeDescription = (): Codec =>
buildCodecForObject()
.property("group", codecForString())
.property("from", codecForAbsoluteTime)
.property("until", codecForAbsoluteTime)
.property("fee", codecOptional(codecForAmountString()))
.build("FeeDescription");
export const codecForFeesByOperations = (): Codec<
DenomOperationMap
> =>
buildCodecForObject>()
.property("deposit", codecForList(codecForFeeDescription()))
.property("withdraw", codecForList(codecForFeeDescription()))
.property("refresh", codecForList(codecForFeeDescription()))
.property("refund", codecForList(codecForFeeDescription()))
.build("DenomOperationMap");
export const codecForExchangeFullDetails = (): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.property("exchangeBaseUrl", codecForString())
.property("paytoUris", codecForList(codecForString()))
.property("auditors", codecForList(codecForExchangeAuditor()))
.property("wireInfo", codecForWireInfo())
.property("denomFees", codecForFeesByOperations())
.property(
"transferFees",
codecForMap(codecForList(codecForFeeDescription())),
)
.property("globalFees", codecForList(codecForFeeDescription()))
.build("ExchangeFullDetails");
export const codecForExchangeListItem = (): Codec =>
buildCodecForObject()
.property("currency", codecForString())
.property("exchangeBaseUrl", codecForString())
.property("paytoUris", codecForList(codecForString()))
.property("tosStatus", codecForAny())
.property("exchangeEntryStatus", codecForAny())
.property("exchangeUpdateStatus", codecForAny())
.property("ageRestrictionOptions", codecForList(codecForNumber()))
.property("scopeInfo", codecForScopeInfo())
.build("ExchangeListItem");
export const codecForExchangesListResponse = (): Codec =>
buildCodecForObject()
.property("exchanges", codecForList(codecForExchangeListItem()))
.build("ExchangesListResponse");
export interface AcceptManualWithdrawalResult {
/**
* Payto URIs that can be used to fund the withdrawal.
*
* @deprecated in favor of withdrawalAccountsList
*/
exchangePaytoUris: string[];
/**
* Public key of the newly created reserve.
*/
reservePub: string;
withdrawalAccountsList: WithdrawalExchangeAccountDetails[];
transactionId: TransactionIdStr;
}
export interface ManualWithdrawalDetails {
/**
* Did the user accept the current version of the exchange's
* terms of service?
*
* @deprecated the client should query the exchange entry instead
*/
tosAccepted: boolean;
/**
* Amount that the user will transfer to the exchange.
*/
amountRaw: AmountString;
/**
* Amount that will be added to the user's wallet balance.
*/
amountEffective: AmountString;
/**
* Number of coins that would be used for withdrawal.
*
* The UIs should warn if this number is too high (roughly at >100).
*/
numCoins: number;
/**
* Ways to pay the exchange.
*
* @deprecated in favor of withdrawalAccountsList
*/
paytoUris: string[];
/**
* Ways to pay the exchange, including accounts that require currency conversion.
*/
withdrawalAccountsList: WithdrawalExchangeAccountDetails[];
/**
* If the exchange supports age-restricted coins it will return
* the array of ages.
*/
ageRestrictionOptions?: number[];
/**
* Scope info of the currency withdrawn.
*/
scopeInfo: ScopeInfo;
}
/**
* Selected denominations withn some extra info.
*/
export interface DenomSelectionState {
totalCoinValue: AmountString;
totalWithdrawCost: AmountString;
selectedDenoms: {
denomPubHash: string;
count: number;
}[];
}
/**
* Information about what will happen doing a withdrawal.
*
* Sent to the wallet frontend to be rendered and shown to the user.
*/
export interface ExchangeWithdrawalDetails {
exchangePaytoUris: string[];
/**
* Filtered wire info to send to the bank.
*/
exchangeWireAccounts: string[];
exchangeCreditAccountDetails: WithdrawalExchangeAccountDetails[];
/**
* Selected denominations for withdraw.
*/
selectedDenoms: DenomSelectionState;
/**
* Did the user already accept the current terms of service for the exchange?
*/
termsOfServiceAccepted: boolean;
/**
* The earliest deposit expiration of the selected coins.
*/
earliestDepositExpiration: TalerProtocolTimestamp;
/**
* Number of currently offered denominations.
*/
numOfferedDenoms: number;
/**
* Public keys of trusted auditors for the currency we're withdrawing.
*/
trustedAuditorPubs: string[];
/**
* Result of checking the wallet's version
* against the exchange's version.
*
* Older exchanges don't return version information.
*/
versionMatch: VersionMatchResult | undefined;
/**
* Libtool-style version string for the exchange or "unknown"
* for older exchanges.
*/
exchangeVersion: string;
/**
* Libtool-style version string for the wallet.
*/
walletVersion: string;
/**
* Amount that will be subtracted from the reserve's balance.
*/
withdrawalAmountRaw: AmountString;
/**
* Amount that will actually be added to the wallet's balance.
*/
withdrawalAmountEffective: AmountString;
/**
* If the exchange supports age-restricted coins it will return
* the array of ages.
*
*/
ageRestrictionOptions?: number[];
}
export interface GetExchangeTosResult {
/**
* Markdown version of the current ToS.
*/
content: string;
/**
* Version tag of the current ToS.
*/
currentEtag: string;
/**
* Version tag of the last ToS that the user has accepted,
* if any.
*/
acceptedEtag: string | undefined;
/**
* Accepted content type
*/
contentType: string;
tosStatus: ExchangeTosStatus;
}
export interface TestPayArgs {
merchantBaseUrl: string;
merchantAuthToken?: string;
amount: AmountString;
summary: string;
forcedCoinSel?: ForcedCoinSel;
}
export const codecForTestPayArgs = (): Codec =>
buildCodecForObject()
.property("merchantBaseUrl", codecForString())
.property("merchantAuthToken", codecOptional(codecForString()))
.property("amount", codecForAmountString())
.property("summary", codecForString())
.property("forcedCoinSel", codecForAny())
.build("TestPayArgs");
export interface IntegrationTestArgs {
exchangeBaseUrl: string;
corebankApiBaseUrl: string;
merchantBaseUrl: string;
merchantAuthToken?: string;
amountToWithdraw: AmountString;
amountToSpend: AmountString;
}
export const codecForIntegrationTestArgs = (): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("merchantBaseUrl", codecForString())
.property("merchantAuthToken", codecOptional(codecForString()))
.property("amountToSpend", codecForAmountString())
.property("amountToWithdraw", codecForAmountString())
.property("corebankApiBaseUrl", codecForString())
.build("IntegrationTestArgs");
export interface IntegrationTestV2Args {
exchangeBaseUrl: string;
corebankApiBaseUrl: string;
merchantBaseUrl: string;
merchantAuthToken?: string;
}
export const codecForIntegrationTestV2Args = (): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("merchantBaseUrl", codecForString())
.property("merchantAuthToken", codecOptional(codecForString()))
.property("corebankApiBaseUrl", codecForString())
.build("IntegrationTestV2Args");
export interface GetExchangeEntryByUrlRequest {
exchangeBaseUrl: string;
}
export const codecForGetExchangeEntryByUrlRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.build("GetExchangeEntryByUrlRequest");
export type GetExchangeEntryByUrlResponse = ExchangeListItem;
export interface AddExchangeRequest {
exchangeBaseUrl: string;
}
export const codecForAddExchangeRequest = (): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.build("AddExchangeRequest");
export interface UpdateExchangeEntryRequest {
exchangeBaseUrl: string;
}
export const codecForUpdateExchangeEntryRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.build("UpdateExchangeEntryRequest");
export interface ForceExchangeUpdateRequest {
exchangeBaseUrl: string;
}
export const codecForForceExchangeUpdateRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.build("AddExchangeRequest");
export interface GetExchangeTosRequest {
exchangeBaseUrl: string;
acceptedFormat?: string[];
}
export const codecForGetExchangeTosRequest = (): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("acceptedFormat", codecOptional(codecForList(codecForString())))
.build("GetExchangeTosRequest");
export interface AcceptManualWithdrawalRequest {
exchangeBaseUrl: string;
amount: AmountString;
restrictAge?: number;
}
export const codecForAcceptManualWithdrawalRequet =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("amount", codecForAmountString())
.property("restrictAge", codecOptional(codecForNumber()))
.build("AcceptManualWithdrawalRequest");
export interface GetWithdrawalDetailsForAmountRequest {
exchangeBaseUrl: string;
amount: AmountString;
restrictAge?: number;
}
export interface AcceptBankIntegratedWithdrawalRequest {
talerWithdrawUri: string;
exchangeBaseUrl: string;
forcedDenomSel?: ForcedDenomSel;
restrictAge?: number;
}
export const codecForAcceptBankIntegratedWithdrawalRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("talerWithdrawUri", codecForString())
.property("forcedDenomSel", codecForAny())
.property("restrictAge", codecOptional(codecForNumber()))
.build("AcceptBankIntegratedWithdrawalRequest");
export const codecForGetWithdrawalDetailsForAmountRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("amount", codecForAmountString())
.property("restrictAge", codecOptional(codecForNumber()))
.build("GetWithdrawalDetailsForAmountRequest");
export interface AcceptExchangeTosRequest {
exchangeBaseUrl: string;
etag: string | undefined;
}
export const codecForAcceptExchangeTosRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecForString())
.property("etag", codecOptional(codecForString()))
.build("AcceptExchangeTosRequest");
export interface AcceptRefundRequest {
transactionId: TransactionIdStr;
}
export const codecForApplyRefundRequest = (): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("AcceptRefundRequest");
export interface ApplyRefundFromPurchaseIdRequest {
purchaseId: string;
}
export const codecForApplyRefundFromPurchaseIdRequest =
(): Codec =>
buildCodecForObject()
.property("purchaseId", codecForString())
.build("ApplyRefundFromPurchaseIdRequest");
export interface GetWithdrawalDetailsForUriRequest {
talerWithdrawUri: string;
restrictAge?: number;
}
export const codecForGetWithdrawalDetailsForUri =
(): Codec =>
buildCodecForObject()
.property("talerWithdrawUri", codecForString())
.property("restrictAge", codecOptional(codecForNumber()))
.build("GetWithdrawalDetailsForUriRequest");
export interface ListKnownBankAccountsRequest {
currency?: string;
}
export const codecForListKnownBankAccounts =
(): Codec =>
buildCodecForObject()
.property("currency", codecOptional(codecForString()))
.build("ListKnownBankAccountsRequest");
export interface AddKnownBankAccountsRequest {
payto: string;
alias: string;
currency: string;
}
export const codecForAddKnownBankAccounts =
(): Codec =>
buildCodecForObject()
.property("payto", codecForString())
.property("alias", codecForString())
.property("currency", codecForString())
.build("AddKnownBankAccountsRequest");
export interface ForgetKnownBankAccountsRequest {
payto: string;
}
export const codecForForgetKnownBankAccounts =
(): Codec =>
buildCodecForObject()
.property("payto", codecForString())
.build("ForgetKnownBankAccountsRequest");
export interface AbortProposalRequest {
proposalId: string;
}
export const codecForAbortProposalRequest = (): Codec =>
buildCodecForObject()
.property("proposalId", codecForString())
.build("AbortProposalRequest");
export interface GetContractTermsDetailsRequest {
proposalId: string;
}
export const codecForGetContractTermsDetails =
(): Codec =>
buildCodecForObject()
.property("proposalId", codecForString())
.build("GetContractTermsDetails");
export interface PreparePayRequest {
talerPayUri: string;
}
export const codecForPreparePayRequest = (): Codec =>
buildCodecForObject()
.property("talerPayUri", codecForString())
.build("PreparePay");
export interface SharePaymentRequest {
merchantBaseUrl: string;
orderId: string;
}
export const codecForSharePaymentRequest = (): Codec =>
buildCodecForObject()
.property("merchantBaseUrl", codecForString())
.property("orderId", codecForString())
.build("SharePaymentRequest");
export interface SharePaymentResult {
privatePayUri: string;
}
export const codecForSharePaymentResult = (): Codec =>
buildCodecForObject()
.property("privatePayUri", codecForString())
.build("SharePaymentResult");
export interface PreparePayTemplateRequest {
talerPayTemplateUri: string;
templateParams: Record;
}
export const codecForPreparePayTemplateRequest =
(): Codec =>
buildCodecForObject()
.property("talerPayTemplateUri", codecForString())
.property("templateParams", codecForAny())
.build("PreparePayTemplate");
export interface ConfirmPayRequest {
/**
* @deprecated use transactionId instead
*/
proposalId?: string;
transactionId?: string;
sessionId?: string;
forcedCoinSel?: ForcedCoinSel;
}
export const codecForConfirmPayRequest = (): Codec =>
buildCodecForObject()
.property("proposalId", codecOptional(codecForString()))
.property("transactionId", codecOptional(codecForString()))
.property("sessionId", codecOptional(codecForString()))
.property("forcedCoinSel", codecForAny())
.build("ConfirmPay");
export interface CoreApiRequestEnvelope {
id: string;
operation: string;
args: unknown;
}
export type CoreApiResponse = CoreApiResponseSuccess | CoreApiResponseError;
export type CoreApiMessageEnvelope = CoreApiResponse | CoreApiNotification;
export interface CoreApiNotification {
type: "notification";
payload: unknown;
}
export interface CoreApiResponseSuccess {
// To distinguish the message from notifications
type: "response";
operation: string;
id: string;
result: unknown;
}
export interface CoreApiResponseError {
// To distinguish the message from notifications
type: "error";
operation: string;
id: string;
error: TalerErrorDetail;
}
export interface WithdrawTestBalanceRequest {
amount: AmountString;
/**
* Corebank API base URL.
*/
corebankApiBaseUrl: string;
exchangeBaseUrl: string;
forcedDenomSel?: ForcedDenomSel;
}
/**
* Request to the crypto worker to make a sync signature.
*/
export interface MakeSyncSignatureRequest {
accountPriv: string;
oldHash: string | undefined;
newHash: string;
}
/**
* Planchet for a coin during refresh.
*/
export interface RefreshPlanchetInfo {
/**
* Public key for the coin.
*/
coinPub: string;
/**
* Private key for the coin.
*/
coinPriv: string;
/**
* Blinded public key.
*/
coinEv: CoinEnvelope;
coinEvHash: string;
/**
* Blinding key used.
*/
blindingKey: string;
maxAge: number;
ageCommitmentProof?: AgeCommitmentProof;
}
/**
* Strategy for loading recovery information.
*/
export enum RecoveryMergeStrategy {
/**
* Keep the local wallet root key, import and take over providers.
*/
Ours = "ours",
/**
* Migrate to the wallet root key from the recovery information.
*/
Theirs = "theirs",
}
/**
* Load recovery information into the wallet.
*/
export interface RecoveryLoadRequest {
recovery: BackupRecovery;
strategy?: RecoveryMergeStrategy;
}
export const codecForWithdrawTestBalance =
(): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("exchangeBaseUrl", codecForString())
.property("forcedDenomSel", codecForAny())
.property("corebankApiBaseUrl", codecForString())
.build("WithdrawTestBalanceRequest");
export interface SetCoinSuspendedRequest {
coinPub: string;
suspended: boolean;
}
export const codecForSetCoinSuspendedRequest =
(): Codec =>
buildCodecForObject()
.property("coinPub", codecForString())
.property("suspended", codecForBoolean())
.build("SetCoinSuspendedRequest");
export interface ForceRefreshRequest {
coinPubList: string[];
}
export const codecForForceRefreshRequest = (): Codec =>
buildCodecForObject()
.property("coinPubList", codecForList(codecForString()))
.build("ForceRefreshRequest");
export interface PrepareRefundRequest {
talerRefundUri: string;
}
export interface StartRefundQueryForUriResponse {
transactionId: TransactionIdStr;
}
export const codecForPrepareRefundRequest = (): Codec =>
buildCodecForObject()
.property("talerRefundUri", codecForString())
.build("PrepareRefundRequest");
export interface StartRefundQueryRequest {
transactionId: TransactionIdStr;
}
export const codecForStartRefundQueryRequest =
(): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("StartRefundQueryRequest");
export interface PrepareRewardRequest {
talerRewardUri: string;
}
export const codecForPrepareRewardRequest = (): Codec =>
buildCodecForObject()
.property("talerRewardUri", codecForString())
.build("PrepareRewardRequest");
export interface AcceptRewardRequest {
walletRewardId: string;
}
export const codecForAcceptTipRequest = (): Codec =>
buildCodecForObject()
.property("walletRewardId", codecForString())
.build("AcceptRewardRequest");
export interface FailTransactionRequest {
transactionId: TransactionIdStr;
}
export const codecForFailTransactionRequest =
(): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("FailTransactionRequest");
export interface SuspendTransactionRequest {
transactionId: TransactionIdStr;
}
export const codecForSuspendTransaction =
(): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("SuspendTransactionRequest");
export interface ResumeTransactionRequest {
transactionId: TransactionIdStr;
}
export const codecForResumeTransaction = (): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("ResumeTransactionRequest");
export interface AbortTransactionRequest {
transactionId: TransactionIdStr;
}
export interface FailTransactionRequest {
transactionId: TransactionIdStr;
}
export const codecForAbortTransaction = (): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("AbortTransactionRequest");
export interface DepositGroupFees {
coin: AmountString;
wire: AmountString;
refresh: AmountString;
}
export interface CreateDepositGroupRequest {
/**
* Pre-allocated transaction ID.
* Allows clients to easily handle notifications
* that occur while the operation has been created but
* before the creation request has returned.
*/
transactionId?: string;
depositPaytoUri: string;
amount: AmountString;
}
export interface PrepareDepositRequest {
depositPaytoUri: string;
amount: AmountString;
}
export const codecForPrepareDepositRequest = (): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("depositPaytoUri", codecForString())
.build("PrepareDepositRequest");
export interface PrepareDepositResponse {
totalDepositCost: AmountString;
effectiveDepositAmount: AmountString;
fees: DepositGroupFees;
}
export const codecForCreateDepositGroupRequest =
(): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("depositPaytoUri", codecForString())
.property("transactionId", codecOptional(codecForString()))
.build("CreateDepositGroupRequest");
export interface CreateDepositGroupResponse {
depositGroupId: string;
transactionId: TransactionIdStr;
}
export interface TxIdResponse {
transactionId: TransactionIdStr;
}
export interface WithdrawUriInfoResponse {
amount: AmountString;
defaultExchangeBaseUrl?: string;
possibleExchanges: ExchangeListItem[];
}
export const codecForWithdrawUriInfoResponse =
(): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("defaultExchangeBaseUrl", codecOptional(codecForString()))
.property("possibleExchanges", codecForList(codecForExchangeListItem()))
.build("WithdrawUriInfoResponse");
export interface WalletCurrencyInfo {
trustedAuditors: {
currency: string;
auditorPub: string;
auditorBaseUrl: string;
}[];
trustedExchanges: {
currency: string;
exchangeMasterPub: string;
exchangeBaseUrl: string;
}[];
}
export interface DeleteTransactionRequest {
transactionId: TransactionIdStr;
}
export interface RetryTransactionRequest {
transactionId: TransactionIdStr;
}
export const codecForDeleteTransactionRequest =
(): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("DeleteTransactionRequest");
export const codecForRetryTransactionRequest =
(): Codec =>
buildCodecForObject()
.property("transactionId", codecForTransactionIdStr())
.build("RetryTransactionRequest");
export interface SetWalletDeviceIdRequest {
/**
* New wallet device ID to set.
*/
walletDeviceId: string;
}
export const codecForSetWalletDeviceIdRequest =
(): Codec =>
buildCodecForObject()
.property("walletDeviceId", codecForString())
.build("SetWalletDeviceIdRequest");
export interface WithdrawFakebankRequest {
amount: AmountString;
exchange: string;
bank: string;
}
export enum AttentionPriority {
High = "high",
Medium = "medium",
Low = "low",
}
export interface UserAttentionByIdRequest {
entityId: string;
type: AttentionType;
}
export const codecForUserAttentionByIdRequest =
(): Codec =>
buildCodecForObject()
.property("type", codecForAny())
.property("entityId", codecForString())
.build("UserAttentionByIdRequest");
export const codecForUserAttentionsRequest = (): Codec =>
buildCodecForObject()
.property(
"priority",
codecOptional(
codecForEither(
codecForConstString(AttentionPriority.Low),
codecForConstString(AttentionPriority.Medium),
codecForConstString(AttentionPriority.High),
),
),
)
.build("UserAttentionsRequest");
export interface UserAttentionsRequest {
priority?: AttentionPriority;
}
export type AttentionInfo =
| AttentionKycWithdrawal
| AttentionBackupUnpaid
| AttentionBackupExpiresSoon
| AttentionMerchantRefund
| AttentionExchangeTosChanged
| AttentionExchangeKeyExpired
| AttentionExchangeDenominationExpired
| AttentionAuditorTosChanged
| AttentionAuditorKeyExpires
| AttentionAuditorDenominationExpires
| AttentionPullPaymentPaid
| AttentionPushPaymentReceived;
export enum AttentionType {
KycWithdrawal = "kyc-withdrawal",
BackupUnpaid = "backup-unpaid",
BackupExpiresSoon = "backup-expires-soon",
MerchantRefund = "merchant-refund",
ExchangeTosChanged = "exchange-tos-changed",
ExchangeKeyExpired = "exchange-key-expired",
ExchangeKeyExpiresSoon = "exchange-key-expires-soon",
ExchangeDenominationsExpired = "exchange-denominations-expired",
ExchangeDenominationsExpiresSoon = "exchange-denominations-expires-soon",
AuditorTosChanged = "auditor-tos-changed",
AuditorKeyExpires = "auditor-key-expires",
AuditorDenominationsExpires = "auditor-denominations-expires",
PullPaymentPaid = "pull-payment-paid",
PushPaymentReceived = "push-payment-withdrawn",
}
export const UserAttentionPriority: {
[type in AttentionType]: AttentionPriority;
} = {
"kyc-withdrawal": AttentionPriority.Medium,
"backup-unpaid": AttentionPriority.High,
"backup-expires-soon": AttentionPriority.Medium,
"merchant-refund": AttentionPriority.Medium,
"exchange-tos-changed": AttentionPriority.Medium,
"exchange-key-expired": AttentionPriority.High,
"exchange-key-expires-soon": AttentionPriority.Medium,
"exchange-denominations-expired": AttentionPriority.High,
"exchange-denominations-expires-soon": AttentionPriority.Medium,
"auditor-tos-changed": AttentionPriority.Medium,
"auditor-key-expires": AttentionPriority.Medium,
"auditor-denominations-expires": AttentionPriority.Medium,
"pull-payment-paid": AttentionPriority.High,
"push-payment-withdrawn": AttentionPriority.High,
};
interface AttentionBackupExpiresSoon {
type: AttentionType.BackupExpiresSoon;
provider_base_url: string;
}
interface AttentionBackupUnpaid {
type: AttentionType.BackupUnpaid;
provider_base_url: string;
talerUri: string;
}
interface AttentionMerchantRefund {
type: AttentionType.MerchantRefund;
transactionId: TransactionIdStr;
}
interface AttentionKycWithdrawal {
type: AttentionType.KycWithdrawal;
transactionId: TransactionIdStr;
}
interface AttentionExchangeTosChanged {
type: AttentionType.ExchangeTosChanged;
exchange_base_url: string;
}
interface AttentionExchangeKeyExpired {
type: AttentionType.ExchangeKeyExpired;
exchange_base_url: string;
}
interface AttentionExchangeDenominationExpired {
type: AttentionType.ExchangeDenominationsExpired;
exchange_base_url: string;
}
interface AttentionAuditorTosChanged {
type: AttentionType.AuditorTosChanged;
auditor_base_url: string;
}
interface AttentionAuditorKeyExpires {
type: AttentionType.AuditorKeyExpires;
auditor_base_url: string;
}
interface AttentionAuditorDenominationExpires {
type: AttentionType.AuditorDenominationsExpires;
auditor_base_url: string;
}
interface AttentionPullPaymentPaid {
type: AttentionType.PullPaymentPaid;
transactionId: TransactionIdStr;
}
interface AttentionPushPaymentReceived {
type: AttentionType.PushPaymentReceived;
transactionId: TransactionIdStr;
}
export type UserAttentionUnreadList = Array<{
info: AttentionInfo;
when: TalerPreciseTimestamp;
read: boolean;
}>;
export interface UserAttentionsResponse {
pending: UserAttentionUnreadList;
}
export interface UserAttentionsCountResponse {
total: number;
}
export const codecForWithdrawFakebankRequest =
(): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("bank", codecForString())
.property("exchange", codecForString())
.build("WithdrawFakebankRequest");
export interface ImportDb {
dump: any;
}
export const codecForImportDbRequest = (): Codec =>
buildCodecForObject()
.property("dump", codecForAny())
.build("ImportDbRequest");
export interface ForcedDenomSel {
denoms: {
value: AmountString;
count: number;
}[];
}
/**
* Forced coin selection for deposits/payments.
*/
export interface ForcedCoinSel {
coins: {
value: AmountString;
contribution: AmountString;
}[];
}
export interface TestPayResult {
payCoinSelection: PayCoinSelection;
}
/**
* Result of selecting coins, contains the exchange, and selected
* coins with their denomination.
*/
export interface PayCoinSelection {
/**
* Amount requested by the merchant.
*/
paymentAmount: AmountString;
/**
* Public keys of the coins that were selected.
*/
coinPubs: string[];
/**
* Amount that each coin contributes.
*/
coinContributions: AmountString[];
/**
* How much of the wire fees is the customer paying?
*/
customerWireFees: AmountString;
/**
* How much of the deposit fees is the customer paying?
*/
customerDepositFees: AmountString;
}
export interface CheckPeerPushDebitRequest {
/**
* Preferred exchange to use for the p2p payment.
*/
exchangeBaseUrl?: string;
/**
* Instructed amount.
*
* FIXME: Allow specifying the instructed amount type.
*/
amount: AmountString;
}
export const codecForCheckPeerPushDebitRequest =
(): Codec =>
buildCodecForObject()
.property("exchangeBaseUrl", codecOptional(codecForString()))
.property("amount", codecForAmountString())
.build("CheckPeerPushDebitRequest");
export interface CheckPeerPushDebitResponse {
amountRaw: AmountString;
amountEffective: AmountString;
exchangeBaseUrl: string;
}
export interface InitiatePeerPushDebitRequest {
exchangeBaseUrl?: string;
partialContractTerms: PeerContractTerms;
}
export interface InitiatePeerPushDebitResponse {
exchangeBaseUrl: string;
pursePub: string;
mergePriv: string;
contractPriv: string;
transactionId: TransactionIdStr;
}
export const codecForInitiatePeerPushDebitRequest =
(): Codec =>
buildCodecForObject()
.property("partialContractTerms", codecForPeerContractTerms())
.build("InitiatePeerPushDebitRequest");
export interface PreparePeerPushCreditRequest {
talerUri: string;
}
export interface PreparePeerPullDebitRequest {
talerUri: string;
}
export interface PreparePeerPushCreditResponse {
contractTerms: PeerContractTerms;
amountRaw: AmountString;
amountEffective: AmountString;
transactionId: string;
exchangeBaseUrl: string;
/**
* @deprecated use transaction ID instead.
*/
peerPushCreditId: string;
/**
* @deprecated
*/
amount: AmountString;
}
export interface PreparePeerPullDebitResponse {
contractTerms: PeerContractTerms;
/**
* @deprecated Redundant field with bad name, will be removed soon.
*/
amount: AmountString;
amountRaw: AmountString;
amountEffective: AmountString;
peerPullDebitId: string;
transactionId: string;
}
export const codecForPreparePeerPushCreditRequest =
(): Codec =>
buildCodecForObject()
.property("talerUri", codecForString())
.build("CheckPeerPushPaymentRequest");
export const codecForCheckPeerPullPaymentRequest =
(): Codec =>
buildCodecForObject()
.property("talerUri", codecForString())
.build("PreparePeerPullDebitRequest");
export interface ConfirmPeerPushCreditRequest {
/**
* Transparent identifier of the incoming peer push payment.
*
* @deprecated specify transactionId instead!
*/
peerPushCreditId?: string;
transactionId?: string;
}
export interface AcceptPeerPushPaymentResponse {
transactionId: TransactionIdStr;
}
export interface AcceptPeerPullPaymentResponse {
transactionId: TransactionIdStr;
}
export const codecForConfirmPeerPushPaymentRequest =
(): Codec =>
buildCodecForObject()
.property("peerPushCreditId", codecOptional(codecForString()))
.property("transactionId", codecOptional(codecForString()))
.build("ConfirmPeerPushCreditRequest");
export interface ConfirmPeerPullDebitRequest {
/**
* Transparent identifier of the incoming peer pull payment.
*
* @deprecated use transactionId instead
*/
peerPullDebitId?: string;
transactionId?: string;
}
export interface ApplyDevExperimentRequest {
devExperimentUri: string;
}
export const codecForApplyDevExperiment =
(): Codec =>
buildCodecForObject()
.property("devExperimentUri", codecForString())
.build("ApplyDevExperimentRequest");
export const codecForAcceptPeerPullPaymentRequest =
(): Codec =>
buildCodecForObject()
.property("peerPullDebitId", codecOptional(codecForString()))
.property("transactionId", codecOptional(codecForString()))
.build("ConfirmPeerPullDebitRequest");
export interface CheckPeerPullCreditRequest {
exchangeBaseUrl?: string;
amount: AmountString;
}
export const codecForPreparePeerPullPaymentRequest =
(): Codec =>
buildCodecForObject()
.property("amount", codecForAmountString())
.property("exchangeBaseUrl", codecOptional(codecForString()))
.build("CheckPeerPullCreditRequest");
export interface CheckPeerPullCreditResponse {
exchangeBaseUrl: string;
amountRaw: AmountString;
amountEffective: AmountString;
/**
* Number of coins that will be used,
* can be used by the UI to warn if excessively large.
*/
numCoins: number;
}
export interface InitiatePeerPullCreditRequest {
exchangeBaseUrl?: string;
partialContractTerms: PeerContractTerms;
}
export const codecForInitiatePeerPullPaymentRequest =
(): Codec =>
buildCodecForObject()
.property("partialContractTerms", codecForPeerContractTerms())
.property("exchangeBaseUrl", codecOptional(codecForString()))
.build("InitiatePeerPullCreditRequest");
export interface InitiatePeerPullCreditResponse {
/**
* Taler URI for the other party to make the payment
* that was requested.
*
* @deprecated since it's not necessarily valid yet until the tx is in the right state
*/
talerUri: string;
transactionId: TransactionIdStr;
}
/**
* Detailed reason for why the wallet's balance is insufficient.
*/
export interface PayPeerInsufficientBalanceDetails {
/**
* Amount requested by the merchant.
*/
amountRequested: AmountString;
/**
* Balance of type "available" (see balance.ts for definition).
*/
balanceAvailable: AmountString;
/**
* Balance of type "material" (see balance.ts for definition).
*/
balanceMaterial: AmountString;
/**
* If non-zero, the largest fee gap estimate of an exchange
* where we would otherwise have enough balance available.
*/
feeGapEstimate: AmountString;
perExchange: {
[url: string]: {
balanceAvailable: AmountString;
balanceMaterial: AmountString;
feeGapEstimate: AmountString;
};
};
}
export interface ValidateIbanRequest {
iban: string;
}
export const codecForValidateIbanRequest = (): Codec =>
buildCodecForObject()
.property("iban", codecForString())
.build("ValidateIbanRequest");
export interface ValidateIbanResponse {
valid: boolean;
}
export const codecForValidateIbanResponse = (): Codec =>
buildCodecForObject()
.property("valid", codecForBoolean())
.build("ValidateIbanResponse");
export type TransactionStateFilter = "nonfinal";
export interface TransactionRecordFilter {
onlyState?: TransactionStateFilter;
onlyCurrency?: string;
}
export interface StoredBackupList {
storedBackups: {
name: string;
}[];
}
export interface CreateStoredBackupResponse {
name: string;
}
export interface RecoverStoredBackupRequest {
name: string;
}
export interface DeleteStoredBackupRequest {
name: string;
}
export const codecForDeleteStoredBackupRequest =
(): Codec =>
buildCodecForObject()
.property("name", codecForString())
.build("DeleteStoredBackupRequest");
export const codecForRecoverStoredBackupRequest =
(): Codec =>
buildCodecForObject()
.property("name", codecForString())
.build("RecoverStoredBackupRequest");
export interface TestingSetTimetravelRequest {
offsetMs: number;
}
export const codecForTestingSetTimetravelRequest =
(): Codec =>
buildCodecForObject()
.property("offsetMs", codecForNumber())
.build("TestingSetTimetravelRequest");
export interface AllowedAuditorInfo {
auditorBaseUrl: string;
auditorPub: string;
}
export interface AllowedExchangeInfo {
exchangeBaseUrl: string;
exchangePub: string;
}
/**
* Data extracted from the contract terms that is relevant for payment
* processing in the wallet.
*/
export interface WalletContractData {
/**
* Fulfillment URL, or the empty string if the order has no fulfillment URL.
*
* Stored as a non-nullable string as we use this field for IndexedDB indexing.
*/
fulfillmentUrl: string;
contractTermsHash: string;
fulfillmentMessage?: string;
fulfillmentMessageI18n?: InternationalizedString;
merchantSig: string;
merchantPub: string;
merchant: MerchantInfo;
amount: AmountString;
orderId: string;
merchantBaseUrl: string;
summary: string;
summaryI18n: { [lang_tag: string]: string } | undefined;
autoRefund: TalerProtocolDuration | undefined;
maxWireFee: AmountString;
wireFeeAmortization: number;
payDeadline: TalerProtocolTimestamp;
refundDeadline: TalerProtocolTimestamp;
allowedExchanges: AllowedExchangeInfo[];
timestamp: TalerProtocolTimestamp;
wireMethod: string;
wireInfoHash: string;
maxDepositFee: AmountString;
minimumAge?: number;
}
export interface TestingWaitTransactionRequest {
transactionId: string;
txState: TransactionState;
}
export interface WithdrawalExchangeAccountDetails {
/**
* Payto URI to credit the exchange.
*
* Depending on whether the (manual!) withdrawal is accepted or just
* being checked, this already includes the subject with the
* reserve public key.
*/
paytoUri: string;
/**
* Status that indicates whether the account can be used
* by the user to send funds for a withdrawal.
*
* ok: account should be shown to the user
* error: account should not be shown to the user, UIs might render the error (in conversionError),
* especially in dev mode.
*/
status: "ok" | "error";
/**
* Transfer amount. Might be in a different currency than the requested
* amount for withdrawal.
*
* Redundant with the amount in paytoUri, just included to avoid parsing.
*
* Only included if this account does a currency conversion.
*/
transferAmount?: AmountString;
/**
* Currency specification for the external currency.
*
* Only included if this account requires a currency conversion.
*/
currencySpecification?: CurrencySpecification;
/**
* Further restrictions for sending money to the
* exchange.
*/
creditRestrictions?: AccountRestriction[];
/**
* Error that happened when attempting to request the conversion rate.
*/
conversionError?: TalerErrorDetail;
}
export interface PrepareWithdrawExchangeRequest {
/**
* A taler://withdraw-exchange URI.
*/
talerUri: string;
}
export const codecForPrepareWithdrawExchangeRequest =
(): Codec =>
buildCodecForObject()
.property("talerUri", codecForString())
.build("PrepareWithdrawExchangeRequest");
export interface PrepareWithdrawExchangeResponse {
/**
* Base URL of the exchange that already existed
* or was ephemerally added as an exchange entry to
* the wallet.
*/
exchangeBaseUrl: string;
/**
* Amount from the taler://withdraw-exchange URI.
* Only present if specified in the URI.
*/
amount?: AmountString;
}
export interface ExchangeEntryState {
tosStatus: ExchangeTosStatus;
exchangeEntryStatus: ExchangeEntryStatus;
exchangeUpdateStatus: ExchangeUpdateStatus;
}