commit f5c1e76de9c9e11cf0e2d176ec5f37564a0437d2
parent b0038ebb43471e46d022a1ff144c5fe3c396b708
Author: Marc Stibane <marc@taler.net>
Date: Sat, 2 Aug 2025 13:48:29 +0200
ContractTermsV1
Diffstat:
1 file changed, 202 insertions(+), 43 deletions(-)
diff --git a/TalerWallet1/Model/Model+Payment.swift b/TalerWallet1/Model/Model+Payment.swift
@@ -16,67 +16,226 @@ import AnyCodable
// readonly d_us: number | "forever";
// }
+struct TokenIssuePublicKey: Codable {
+ let cipher: String // "RSA", "CS"
+
+ // RSA public key
+ let rsaPub: String? // RSA public key converted to Crockford Base32
+
+ // CS public key
+ let csPub: String? // 32-byte value representing a point on Curve25519
+
+ // Start time of this key's signatures validity period
+ let signatureValidityStart: Timestamp
+
+ // End time of this key's signatures validity period
+ let signatureValidityEnd: Timestamp
+
+ enum CodingKeys: String, CodingKey {
+ case cipher
+ case rsaPub = "rsa_pub"
+ case csPub = "cs_pub"
+ case signatureValidityStart = "signature_validity_start"
+ case signatureValidityEnd = "signature_validity_end"
+ }
+}
+
+struct ContractTokenDetails: Codable {
+ let clazz: String // "subscription", "discount"
+
+ // Array of domain names where this subscription can be safely used
+ // (e.g. the issuer warrants that these sites will re-issue tokens of this type
+ // if the respective contract says so). May contain "*" for any domain or subdomain.
+ let trustedDomains: [String]? // only for subscription
+
+ // Array of domain names where this discount token is intended to be used.
+ // May contain "*" for any domain or subdomain. Users should be warned about sites
+ // proposing to consume discount tokens of this type that are not in this list that
+ // the merchant is accepting a coupon from a competitor and thus may be attaching
+ // different semantics (like get 20% discount for my competitors 30% discount token).
+ let expectedDomains: [String]? // only for discount
+
+ enum CodingKeys: String, CodingKey {
+ case clazz = "class"
+ case trustedDomains = "trusted_domains"
+ case expectedDomains = "expected_domains"
+ }
+}
+
+struct ContractTokenFamily: Codable {
+ // Human-readable name of the token family.
+ let name: String
+
+ // Human-readable description of the semantics of this token family (for display).
+ let description: String
+
+ // Map from IETF BCP 47 language tags to localized descriptions.
+ let descriptionI18n: [String: String]?
+
+ // Public keys used to validate tokens issued by this token family.
+ let keys: [TokenIssuePublicKey]
+
+ // Kind-specific information of the token
+ let details: ContractTokenDetails
+
+ // Must a wallet understand this token type to
+ // process contracts that use or issue it?
+ let critical: Bool
+
+ enum CodingKeys: String, CodingKey {
+ case name, description
+ case descriptionI18n = "description_i18n"
+ case keys, details, critical
+ }
+}
+
+struct ContractInput: Codable {
+ let type: String // "token"
+
+ // Slug of the token family in the token_families map on the order
+ let tokenFamilySlug: String?
+
+ // Number of tokens of this type required.
+ // Defaults to one if the field is not provided.
+ let count: Int?
+
+ enum CodingKeys: String, CodingKey {
+ case type, count
+ case tokenFamilySlug = "token_family_slug"
+ }
+}
+
+struct ContractOutput: Codable {
+ let type: String // "token"
+
+ // Slug of the token family in the token_families map on the order
+ let tokenFamilySlug: String?
+
+ // Number of tokens of this type required.
+ // Defaults to one if the field is not provided.
+ let count: Int?
+
+ // Index of the public key for this output token
+ // in the ContractTokenFamily keys array.
+ let keyIndex: Int
+
+ enum CodingKeys: String, CodingKey {
+ case type, count
+ case tokenFamilySlug = "token_family_slug"
+ case keyIndex = "key_index"
+ }
+}
+
+struct ContractOutputTaxReceipt: Codable {
+ let type: String // "tax-receipt"
+
+ // Array of base URLs of donation authorities that can be
+ // used to issue the tax receipts. The client must select one.
+ let donauUrls: [String]
+
+ // Total amount that will be on the tax receipt.
+ let amount: Amount
+
+ enum CodingKeys: String, CodingKey {
+ case type, amount
+ case donauUrls = "donau_urls"
+ }
+}
+
+struct ContractChoice: Codable {
+ let amount: Amount // Total amount payable
+ let maxFee: Amount // Maximum deposit fee covered by the merchant
+ let description: String? //
+ let descriptionI18n: [String: String]? // " localized "
+ let inputs: [ContractInput]
+ let outputs: [ContractOutput]
+
+ enum CodingKeys: String, CodingKey {
+ case amount, maxFee, description
+ case descriptionI18n = "description_i18n"
+ case inputs, outputs
+ }
+}
+
struct MerchantContractTerms: Codable {
- let hWire: String // Hash of the merchant's wire details
-// let autoRefund: String? // TODO: TalerProtocolDuration
- let wireMethod: String // merchant wants to use
+ let version: Int?
+
+ // ContractTermsV0
+ let amount: Amount? // Total amount payable
+ let maxFee: Amount? // Maximum deposit fee covered by the merchant
+
+ // ContractTermsCommon
let summary: String // Human-readable short summary of the contract
- let summaryI18n: [String:String]? // " localized "
- let nonce: String // used to ensure freshness
- let amount: Amount // Total amount payable
- let payDeadline: Timestamp // Deadline to pay for the contract
- let maxFee: Amount // Maximum deposit fee covered by the merchant
- let merchant: Merchant
- let merchantPub: String // Public key of the merchant
- let deliveryDate: Timestamp? // indicating when the order should be delivered
- let deliveryLocation: Location? // Delivery location for (all!) products
- let exchanges: [ExchangeForPay]
- let products: [Product]? // Products that are sold in this contract
- let refundDeadline: Timestamp // Deadline for refunds
- let wireTransferDeadline: Timestamp // Deadline for the wire transfer
- let timestamp: Timestamp // Time when the contract was generated by the merchant
+ let summaryI18n: [String: String]? // " localized "
let orderID: String // uniquely identify the purchase within one merchant instance
- let merchantBaseURL: String // Base URL of the merchant's backend
- let fulfillmentURL: String? // Fulfillment URL to view the product or delivery status
let publicReorderURL: String? // URL meant to share the shopping cart
+ let fulfillmentURL: String? // Fulfillment URL to view the product or delivery status
let fulfillmentMessage: String? // Plain text fulfillment message in the merchant's default language
let fulfillmentMessageI18n: String? // Plain text fulfillment message in the merchant's default language
- let wireFeeAmortization: Int? // Share of the wire fee that must be settled with one payment
- let maxWireFee: Amount? // Maximum wire fee that the merchant agrees to pay for
+ let products: [Product]? // Products that are sold in this contract
+ let timestamp: Timestamp // Time when the contract was generated by the merchant
+ let refundDeadline: Timestamp // Deadline for refunds
+ let payDeadline: Timestamp // Deadline to pay for the contract
+ let wireTransferDeadline: Timestamp // Deadline for the wire transfer
+ let merchantPub: String // Public key of the merchant
+ let merchantBaseURL: String // Base URL of the merchant's backend
+ let merchant: Merchant
+ let hWire: String // Hash of the merchant's wire details
+ let wireMethod: String // merchant wants to use
+ let exchanges: [ExchangeForPay]
+ let deliveryLocation: Location? // Delivery location for (all!) products
+ let deliveryDate: Timestamp? // indicating when the order should be delivered
+ let nonce: String // used to ensure freshness
+ let autoRefund: String? // TODO: TalerProtocolDuration
+ let extra: Extra? // Extra data, interpreted by the merchant only
let minimumAge: Int?
-// let extra: Extra? // Extra data, interpreted by the mechant only
+
+// deprecated let wireFeeAmortization: Int? // Share of the wire fee that must be settled with one payment
+// let maxWireFee: Amount? // Maximum wire fee that the merchant agrees to pay for
// let auditors: [Auditor]?
+ // ContractTermsV1
+ let choices: [ContractChoice]?
+ // Map of storing metadata and issue keys of
+ // token families referenced in this contract.
+ // @since protocol **vSUBSCRIBE**
+ let tokenFamilies: [String: ContractTokenFamily]?
+
enum CodingKeys: String, CodingKey {
- case hWire = "h_wire"
-// case autoRefund = "auto_refund"
- case wireMethod = "wire_method"
- case summary
- case summaryI18n = "summary_i18n"
- case nonce
+ case version
case amount
- case payDeadline = "pay_deadline"
case maxFee = "max_fee"
- case merchant
- case merchantPub = "merchant_pub"
- case deliveryDate = "delivery_date"
- case deliveryLocation = "delivery_location"
- case exchanges
- case products
- case refundDeadline = "refund_deadline"
- case wireTransferDeadline = "wire_transfer_deadline"
- case timestamp
+
+ case summary
+ case summaryI18n = "summary_i18n"
case orderID = "order_id"
- case merchantBaseURL = "merchant_base_url"
- case fulfillmentURL = "fulfillment_url"
case publicReorderURL = "public_reorder_url"
+ case fulfillmentURL = "fulfillment_url"
case fulfillmentMessage = "fulfillment_message"
case fulfillmentMessageI18n = "fulfillment_message_i18n"
- case wireFeeAmortization = "wire_fee_amortization"
- case maxWireFee = "max_wire_fee"
+ case products
+ case timestamp
+ case refundDeadline = "refund_deadline"
+ case payDeadline = "pay_deadline"
+ case wireTransferDeadline = "wire_transfer_deadline"
+ case merchantPub = "merchant_pub"
+ case merchantBaseURL = "merchant_base_url"
+ case merchant
+ case hWire = "h_wire"
+ case wireMethod = "wire_method"
+ case exchanges
+ case deliveryLocation = "delivery_location"
+ case deliveryDate = "delivery_date"
+ case nonce
+ case autoRefund = "auto_refund"
+ case extra
case minimumAge = "minimum_age"
-// case extra
+
+// case wireFeeAmortization = "wire_fee_amortization"
+// case maxWireFee = "max_wire_fee"
// case auditors
+ case choices
+ case tokenFamilies = "token_families"
}
}
// MARK: - Auditor