Contents

POST /purses/$PURSE_PUB/create#

Create a purse by depositing money into it. First step of a PUSH payment.

Request:

The request body must be a PurseCreate object.

Response:

200 OK:

The operation succeeded, the exchange confirms that all coins were deposited into the purse. The response will include a PurseCreateSuccessResponse object.

403 Forbidden:

A coin, denomination or contract signature is invalid. This response comes with a standard ErrorDetail response.

404 Not Found:

The denomination of one of the coins is unknown to the exchange.

409 Conflict:

The deposit operation has either failed because a coin has insufficient residual value, or because the same public key of the coin has been previously used with a different denomination, or because a purse with the same public key but different meta data was created previously. Which case it is can be decided by looking at the error code (TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS or TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY or TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA or TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA or TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA). The specific fields of the response depend on the error code and include the signatures (and what was signed over) proving the conflict.

425 Too Early:

This response type is used if the given purse expiration time is too far in the future (at least from the perspective of the exchange). Thus, retrying at a later time may succeed. The client should look at the Date: header of the response to see if a minor time difference is to blame and possibly adjust the request accordingly. (Note: this status code is not yet used.)

Details:

interface PurseCreate {

  // Total value of the purse, excluding fees.
  amount: Amount;

  // Minimum age required for all coins deposited into the purse.
  min_age: Integer;

  // Optional encrypted contract, in case the buyer is
  // proposing the contract and thus establishing the
  // purse with the payment.
  econtract?: EncryptedContract;

  // EdDSA public key used to approve merges of this purse.
  merge_pub: EddsaPublicKey;

  // EdDSA signature of the purse over a
  // TALER_PurseRequestSignaturePS
  // of purpose TALER_SIGNATURE_WALLET_PURSE_CREATE
  // confirming the key
  // invariants associated with the purse.
  // (amount, h_contract_terms, expiration).
  purse_sig: EddsaSignature;

  // SHA-512 hash of the contact of the purse.
  h_contract_terms: HashCode;

  // Array of coins being deposited into the purse.
  // Maximum length is 128.
  deposits: PurseDeposit[];

  // Indicative time by which the purse should expire
  // if it has not been merged into an account. At this
  // point, all of the deposits made will be auto-refunded.
  purse_expiration: Timestamp;

}
interface EncryptedContract {

  // Encrypted contract.
  econtract: string;

  // Signature over the (encrypted) contract.
  econtract_sig: EddsaSignature;

  // Ephemeral public key for the DH operation to decrypt the encrypted contract.
  contract_pub: EddsaPublicKey;

}
 interface PurseCreateSuccessResponse {

  // Total amount deposited into the purse so far (without fees).
  total_deposited: Amount;

  // Time at the exchange.
  exchange_timestamp: Timestamp;

  // EdDSA signature of the exchange affirming the payment,
  // of purpose TALER_SIGNATURE_PURSE_DEPOSIT_CONFIRMED
  // over a TALER_PurseDepositConfirmedSignaturePS.
  // Signs over the above and the purse public key and
  // the hash of the contract terms.
  exchange_sig: EddsaSignature;

  // public key used to create the signature.
  exchange_pub: EddsaPublicKey;

}
// Union discriminated by the "code" field.
type PurseConflict =
| DepositDoubleSpendError
| PurseCreateConflict
| PurseDepositConflict
| PurseContractConflict;
interface PurseCreateConflict {
  // Must be equal to TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA
  code: Integer;

  // Total amount to be merged into the reserve.
  // (excludes fees).
  amount: Amount;

  // Minimum age required for all coins deposited into the purse.
  min_age: Integer;

  // Indicative time by which the purse should expire
  // if it has not been merged into an account. At this
  // point, all of the deposits made should be
  // auto-refunded.
  purse_expiration: Timestamp;

  // EdDSA signature of the purse over
  // TALER_PurseMergeSignaturePS of
  // purpose TALER_SIGNATURE_WALLET_PURSE_MERGE
  // confirming that the
  // above details hold for this purse.
  purse_sig: EddsaSignature;

  // SHA-512 hash of the contact of the purse.
  h_contract_terms: HashCode;

  // EdDSA public key used to approve merges of this purse.
  merge_pub: EddsaPublicKey;
}
interface PurseDepositConflict {
  // Must be equal to TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA
  code: Integer;

  // Public key of the coin being deposited into the purse.
  coin_pub: EddsaPublicKey;

  // Signature over TALER_PurseDepositSignaturePS
  // of purpose TALER_SIGNATURE_WALLET_PURSE_DEPOSIT
  // made by the customer with the
  // coin's private key.
  coin_sig: EddsaSignature;

  // Target exchange URL for the purse. Not present for the
  // same exchange.
  partner_url?: string;

  // Amount to be contributed to the purse by this coin.
  amount: Amount;

}
interface PurseContractConflict {
  // Must be equal to TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA
  code: Integer;

  // Hash of the encrypted contract.
  h_econtract: HashCode;

  // Signature over the contract.
  econtract_sig: EddsaSignature;

  // Ephemeral public key for the DH operation to decrypt the contract.
  contract_pub: EddsaPublicKey;

}