Contents

POST /batch-deposit#

Deposit multiple coins and ask the exchange to transfer the given Amounts into the merchant’s bank account. This API is used by the merchant to redeem the digital coins.

Request:

The request body must be a BatchDepositRequest object.

Response:

200 OK:

The operation succeeded, the exchange confirms that no double-spending took place. The response will include a DepositSuccess object.

403 Forbidden:

One of the signatures is invalid. This response comes with a standard ErrorDetail response.

404 Not found:

Either one of the denomination keys is not recognized (expired or invalid), or the wire type is not recognized. If a denomination key is unknown, the response will be a DenominationUnknownMessage.

409 Conflict:

The deposit operation has either failed because a coin has insufficient residual value, or because the same public key of a coin has been previously used with a different denomination. Which case it is can be decided by looking at the error code:

  1. TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT (same coin used in different ways),

  2. TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS (balance insufficient),

  3. TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY (same coin public key, but different denomination).

  4. TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH (same coin public key, but different age commitment).

The request should not be repeated again with this coin. Instead, the client can get from the exchange via the /coin/$COIN_PUB/history endpoint the record of the transactions known for this coin’s public key.

410 Gone:

The requested denomination key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a DenominationGoneMessage. Clients must evaluate the error code provided to understand which of the cases this is and handle it accordingly.

451 Unavailable For Legal Reasons:

This merchant has not yet passed the KYC checks. The client must pass KYC checks before proceeding with the deposit. The response will be an LegitimizationNeededResponse object. @since protocol v21.

Details:

interface BatchDepositRequest {

  // The merchant's account details as a full payto URI.
  merchant_payto_uri: string;

  // The salt is used to hide the payto_uri from customers
  // when computing the h_wire of the merchant.
  wire_salt: WireSalt;

  // SHA-512 hash of the contract of the merchant with the customer.  Further
  // details are never disclosed to the exchange.
  h_contract_terms: HashCode;

  // Merchant's signature over the h_contract_terms.
  // @since protocol **v22**
  merchant_sig: EddsaSignature;

  // The list of coins that are going to be deposited with this Request.
  coins: BatchDepositRequestCoin[];

  // Timestamp when the contract was finalized.
  timestamp: Timestamp;

  // Indicative time by which the exchange undertakes to transfer the funds to
  // the merchant, in case of successful payment. A wire transfer deadline of 'never'
  // is not allowed.
  wire_transfer_deadline: Timestamp;

  // EdDSA public key of the merchant, so that the client can identify the
  // merchant for refund requests.
  merchant_pub: EddsaPublicKey;

  // Additional text to include in the wire transfer subject when
  // settling the payment. Note that the merchant MUST use this
  // consistently for the same merchant_pub and merchant_payto_uri
  // as during aggregation *any* of these values may be selected
  // for the actual aggregated wire transfer. If a merchant wants
  // to use different extra_subject values for the same IBAN,
  // it should thus create multiple instances (with different
  // merchant_pub values). When changing the extra_subject,
  // the change may thus not be immediately reflected in the
  // settlements.
  //
  // Must match [a-zA-Z0-9-.:]{1, 40}
  //
  // Optional. Since **v32**.
  extra_wire_subject_metadata?: string;

  // Date until which the merchant can issue a refund to the customer via the
  // exchange, to be omitted if refunds are not allowed.
  //
  // THIS FIELD WILL BE DEPRICATED, once the refund mechanism becomes a
  // policy via extension.
  refund_deadline?: Timestamp;

  // CAVEAT: THIS IS WORK IN PROGRESS
  // (Optional) policy for the batch-deposit.
  // This might be a refund, auction or escrow policy.
  policy?: DepositPolicy;
}
interface BatchDepositRequestCoin {
  // EdDSA public key of the coin being deposited.
  coin_pub: EddsaPublicKey;

  // Hash of denomination RSA key with which the coin is signed.
  denom_pub_hash: HashCode;

  // Exchange's unblinded RSA signature of the coin.
  ub_sig: DenominationSignature;

  // Amount to be deposited, can be a fraction of the
  // coin's total value.
  contribution: Amount;

  // Signature over TALER_DepositRequestPS, made by the customer with the
  // coin's private key.
  coin_sig: EddsaSignature;
}
type DenominationSignature = DenomCipher & (
  | RsaDenominationSignature
  | CSDenominationSignature
);
interface RsaDenominationSignature extends DenomCipher {
  cipher: "RSA";

  // RSA signature
  rsa_signature: RsaSignature;
}
interface CSDenominationSignature extends DenomCipher {
  cipher: "CS";

  // R value component of the signature.
  cs_signature_r: Cs25519Point;

  // s value component of the signature.
  cs_signature_s: Cs25519Scalar;

}
// CAVEAT: THIS IS STILL WORK IN PROGRESS.
// This policy is optional and might not be supported by the exchange.
// If it does, the exchange MUST show support for this policy in the
// extensions field in the response to /keys.
interface PolicyMerchantRefund {
  type: "merchant_refund";

  // EdDSA public key of the merchant, so that the client
  // can identify the merchant for refund requests.
  merchant_pub: EddsaPublicKey;

  // Date until which the merchant can issue a refund to the customer via
  // the /extensions/policy_refund-endpoint of the exchange.
  deadline: Timestamp;
}
// CAVEAT: THIS IS STILL WORK IN PROGRESS.
// This policy is optional and might not be supported by the exchange.
// If it does, the exchange MUST show support for this policy in the
// extensions field in the response to /keys.
interface PolicyBrandtVickreyAuction {
  type: "brandt_vickrey_auction";

  // Public key of this bidder.
  //
  // The bidder uses this key to sign the auction information and
  // the messages it sends to the seller during the auction.
  bidder_pub: EddsaPublicKey;

  // Hash of the auction terms
  //
  // The hash should be taken over a normalized JSON object of type
  // BrandtVickreyAuction.
  h_auction: HashCode;

  // The amount that this bidder commits to for this auction
  //
  // This amount can be larger than the contribution of a single coin.
  // The bidder can increase funding of this auction policy by using
  // sufficiently many coins during the deposit operation (single or batch)
  // with the same policy.
  commitment: Amount;

  // Date until the auction must have been successfully executed and
  // a valid transcript provided to the
  // /extensions/policy_brandt_vickrey_auction-endpoint of the
  // exchange.
  //
  // [If the auction has not been executed by then] OR [has been executed
  // before then, but this bidder did not win], the coin's value doesn't
  // change and the owner can refresh the coin.
  //
  // If this bidder won the auction, the winning price/amount from the
  // outcome will be substracted from the coin and transfered to the
  // merchant's payout_uri from the deposit request (minus a potential
  // auction fee).  For any remaining value, the bidder can refresh the
  // coin to retrieve change.
  deadline: Timestamp;
}
// CAVEAT: THIS IS STILL WORK IN PROGRESS.
// This structure defines an auction of Brandt-Vickory kind.
// It is used for the PolicyBrandtVickreyAuction.
interface BrandtVickreyAuction {
  // Start date of the auction
  time_start: Timestamp;

  // Maximum duration per round.  There are four rounds in an auction of
  // Brandt-Vickrey kind.
  time_round: RelativeTime;

  // This integer m refers to the (m+1)-type of the Brandt-Vickrey-auction.
  // - Type 0 refers to an auction with one highest-price winner,
  // - Type 1 refers to an auction with one winner, paying the second
  //   highest price,
  // - Type 2 refers to an auction with two winners, paying
  //   the third-highest price,
  // - etc.
  auction_type: Integer;

  // The vector of prices for the Brandt-Vickrey auction.  The values MUST
  // be in strictly increasing order.
  prices: Amount[];

  // The type of outcome of the auction.
  // In case the auction is declared public, each bidder can calculate the
  // winning price.  This field is not relevant for the replay of a
  // transcript, as the transcript must be provided by the seller who sees
  // the winner(s) and winning price of the auction.
  outcome_public: boolean;

  // The public key of the seller.
  pubkey: EddsaPublicKey;

  // The seller's account details as a full payto URI.
  payto_uri: string;
}
// CAVEAT: THIS IS STILL WORK IN PROGRESS
// This policy is optional and might not be supported by the exchange.
// If it does, the exchange MUST show support for this policy in the
// extensions field in the response to /keys.
interface PolicyEscrowedPayment {
  type: "escrowed_payment";

  // Public key of this trustor, the owner of the coins.
  //
  // To claim the deposit, the merchant must provide the valid signature
  // of the h_contract_terms field from the deposit, signed by _this_
  // key, to the /extensions/policy_escrow-endpoint of the exchange,
  // after the date specified in not_before and before the date
  // specified in not_after.
  trustor_pub: EddsaPublicKey;

  // Latest date by which the deposit must be claimed.  If the deposit
  // has not been claimed by that date, the deposited coins can be
  // refreshed by the (still) owner.
  deadline: Timestamp;
}

The deposit operation succeeds if the coin is valid for making a deposit and has enough residual value that has not already been deposited or melted.

 interface DepositSuccess {
  // Optional base URL of the exchange for looking up wire transfers
  // associated with this transaction.  If not given,
  // the base URL is the same as the one used for this request.
  // Can be used if the base URL for /transactions/ differs from that
  // for /coins/, i.e. for load balancing.  Clients SHOULD
  // respect the transaction_base_url if provided.  Any HTTP server
  // belonging to an exchange MUST generate a 307 or 308 redirection
  // to the correct base URL should a client uses the wrong base
  // URL, or if the base URL has changed since the deposit.
  transaction_base_url?: string;

  // Timestamp when the deposit was received by the exchange.
  exchange_timestamp: Timestamp;

  // Public EdDSA key of the exchange that was used to
  // generate the signature.
  // Should match one of the exchange's signing keys from /keys.  It is given
  // explicitly as the client might otherwise be confused by clock skew as to
  // which signing key was used.
  exchange_pub: EddsaPublicKey;

  // Deposit confirmation signature from the exchange.
  // The EdDSA signature of TALER_DepositConfirmationPS using a current
  // signing key of the exchange affirming the successful
  // deposit and that the exchange will transfer the funds after the refund
  // deadline, or as soon as possible if the refund deadline is zero.
  exchange_sig: EddsaSignature;
}
interface DepositDoubleSpendError {

  // Must be TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS
  // or TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY
  code: Integer;

  // A string explaining that the user tried to
  // double-spend.
  hint: string;

  // EdDSA public key of a coin being double-spent.
  coin_pub: EddsaPublicKey;

  // Hash of the public key of the denomination of the coin.
  h_denom_pub: HashCode;

}