(* TODO ppx? normalized JSON-object for signature of ExchangeKeysResponse.exetensions field why is this one not defined by a struct? how to handle protocol versions: - "@deprecated" fields - "@since protocol xx" better jsont cases handling: - factorize common fields (DenomCommon/DenomGroupCommon) - "+age_restricted"/CS variants - raise error not implemented if not RSA monotonic time payto_uri uri option: correct use opt_mem or Jsont.option number - number is "float", but we probably want int everywhere instead - numeric values capped at 2^53 -1 inclusive because json *) open Crypto open Bin_signature open Jsont.Object let encode_exn jsont v = Jsont_bytesrw.encode_string jsont v |> Result.get_ok let encode jsont v = Jsont_bytesrw.encode_string jsont v let decode jsont v = Jsont_bytesrw.decode_string jsont v module Account_operation = struct type t = | Withdraw | Deposit | Merge | Balance | Close | Aggregate | Transaction | Refund let to_string t = String.uppercase_ascii @@ match t with | Withdraw -> "withdraw" | Deposit -> "deposit" | Merge -> "merge" | Balance -> "balance" | Close -> "close" | Aggregate -> "aggregate" | Transaction -> "transaction" | Refund -> "refund" let jsont = [ Withdraw; Deposit; Merge; Balance; Close; Aggregate; Transaction; Refund ] |> List.map (fun t -> (to_string t, t)) |> Jsont.enum ~kind:"account operation type" end (* TODO error response - use GANA error codes https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/registry.rec *) module ErrorDetail = struct type t = { code: int; hint: string option; } let jsont = let make code hint = { code; hint } in let enc_code v = v.code in let enc_hint v = v.hint in Jsont.Object.map ~kind:"ErrorDetail" make |> Jsont.Object.mem "code" Jsont.int ~enc:enc_code |> Jsont.Object.opt_mem "hint" Jsont.string ~enc:enc_hint |> Jsont.Object.finish end module B32 = struct include B32 let jsont = Jsont.of_of_string ~kind:"B32" B32.decode ~enc:B32.encode end module HashCode : sig type t val hash : string -> t val jsont : t Jsont.t end = struct type t = B32.t let hash s = let open Digestif.SHA512 in s |> digest_string |> to_raw_string let jsont = B32.jsont end module RelativeTime = struct type t = | Microseconds of float | Forever let number_or_forever_jsont = let forever = let dec s = match s with | "forever" -> Forever | _ -> Jsont.Error.msg Jsont.Meta.none "unexpected string value" in let enc = function Forever -> "forever" | _ -> assert false in Jsont.map ~dec ~enc Jsont.string in let number = let dec n = Microseconds n in let enc = function Microseconds n -> n | _ -> assert false in Jsont.map ~dec ~enc Jsont.number in let enc = function Forever -> forever | Microseconds _ -> number in Jsont.any ~dec_string:forever ~dec_number:number ~enc () let jsont = let make t_s = t_s in Jsont.Object.map ~kind:"RelativeTime" make |> Jsont.Object.mem "t_s" number_or_forever_jsont ~enc:Fun.id |> Jsont.Object.finish end module CurrencySpecification = struct type t = { name: string; num_fractional_input_digits: int; num_fractional_normal_digits: int; num_fractional_trailing_zero_digits: int; alt_unit_names: string; common_amounts: Amount.t list; } let jsont = let make name num_fractional_input_digits num_fractional_normal_digits num_fractional_trailing_zero_digits alt_unit_names common_amounts = { name; num_fractional_input_digits; num_fractional_normal_digits; num_fractional_trailing_zero_digits; alt_unit_names; common_amounts; } in let name v = v.name in let num_fractional_input_digits v = v.num_fractional_input_digits in let num_fractional_normal_digits v = v.num_fractional_normal_digits in let num_fractional_trailing_zero_digits v = v.num_fractional_trailing_zero_digits in let alt_unit_names v = v.alt_unit_names in let common_amounts v = v.common_amounts in map ~kind:"CurrencySpecification" make |> mem "name" Jsont.string ~enc:name |> mem "num_fractional_input_digits" Jsont.int ~enc:num_fractional_input_digits |> mem "num_fractional_normal_digits" Jsont.int ~enc:num_fractional_normal_digits |> mem "num_fractional_trailing_zero_digits" Jsont.int ~enc:num_fractional_trailing_zero_digits |> mem "alt_unit_names" Jsont.string ~enc:alt_unit_names |> mem "common_amounts" (Jsont.list Amount.jsont) ~enc:common_amounts |> finish end module ExchangeVersionResponse = struct type t = { version: string; (* todo: const string name: "taler-exchange";*) implementation: string option; currency: string; shopping_url: string option; open_banking_gateway: string option; currency_specification: CurrencySpecification.t; supported_kyc_requirements: string list; aml_spa_dialect: string option; } let jsont = let make version implementation currency shopping_url open_banking_gateway currency_specification supported_kyc_requirements aml_spa_dialect = { version; implementation; currency; shopping_url; open_banking_gateway; currency_specification; supported_kyc_requirements; aml_spa_dialect; } in let version v = v.version in let implementation v = v.implementation in let currency v = v.currency in let shopping_url v = v.shopping_url in let open_banking_gateway v = v.open_banking_gateway in let currency_specification v = v.currency_specification in let supported_kyc_requirements v = v.supported_kyc_requirements in let aml_spa_dialect v = v.aml_spa_dialect in map ~kind:"ExchangeVersionResponse" make |> mem "version" Jsont.string ~enc:version |> mem "implementation" (Jsont.option Jsont.string) ~enc:implementation |> mem "currency" Jsont.string ~enc:currency |> mem "shopping_url" (Jsont.option Jsont.string) ~enc:shopping_url |> mem "open_banking_gateway" (Jsont.option Jsont.string) ~enc:open_banking_gateway |> mem "currency_specification" CurrencySpecification.jsont ~enc:currency_specification |> mem "supported_kyc_requirements" (Jsont.list Jsont.string) ~enc:supported_kyc_requirements |> mem "aml_spa_dialect" (Jsont.option Jsont.string) ~enc:aml_spa_dialect |> finish end module RsaDenominationKey = struct type t = { age_mask: int; rsa_pub: RsaPublicKey.t; } let jsont = let make age_mask rsa_pub = { age_mask; rsa_pub } in let age_mask v = v.age_mask in let rsa_pub v = v.rsa_pub in Jsont.Object.map ~kind:"RsaDenominationKey" make |> Jsont.Object.mem "age_mask" Jsont.int ~enc:age_mask |> Jsont.Object.mem "rsa_pub" RsaPublicKey.jsont ~enc:rsa_pub |> Jsont.Object.finish end (* ! Clause Schnorr cipher is not supported *) module CSDenominationKey = struct type t = { age_mask: int; cs_pub: B32.t; } let jsont = let make age_mask cs_pub = { age_mask; cs_pub } in let age_mask v = v.age_mask in let cs_pub v = v.cs_pub in Jsont.Object.map ~kind:"CSDenominationKey" make |> Jsont.Object.mem "age_mask" Jsont.int ~enc:age_mask |> Jsont.Object.mem "cs_pub" B32.jsont ~enc:cs_pub |> Jsont.Object.finish end module DenominationKey = struct type t = Rsa of RsaDenominationKey.t (*| CS of CSDenominationKey.t*) let to_octets = function Rsa denom -> RsaPublicKey.to_octets denom.rsa_pub let of_cs _v = Jsont.Error.msg Jsont.Meta.none "CSDenominationKey are not supported" let of_rsa v = Rsa v let jsont = let rsa = Case.map "RSA" RsaDenominationKey.jsont ~dec:of_rsa in let cs = Case.map "CS" CSDenominationKey.jsont ~dec:of_cs in let enc_case = function Rsa v -> Case.value rsa v in let cases = Case.[ make rsa; make cs ] in map ~kind:"DenominationKey" Fun.id |> case_mem "cipher" Jsont.string ~enc:Fun.id ~enc_case cases |> finish end module FutureSignKey = struct type t = { key: EddsaPublicKey.t; stamp_start: Timestamp.t; stamp_expire: Timestamp.t; stamp_end: Timestamp.t; signkey_secmod_sig: SigningKeyAnnouncementPS.t; } let jsont = let make key stamp_start stamp_expire stamp_end signkey_secmod_sig = { key; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig } in let key v = v.key in let stamp_start v = v.stamp_start in let stamp_expire v = v.stamp_expire in let stamp_end v = v.stamp_end in let signkey_secmod_sig v = v.signkey_secmod_sig in map ~kind:"FutureSignKey" make |> mem "key" EddsaPublicKey.jsont ~enc:key |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_expire" Timestamp.jsont ~enc:stamp_expire |> mem "stamp_end" Timestamp.jsont ~enc:stamp_end |> mem "signkey_secmod_sig" SigningKeyAnnouncementPS.jsont ~enc:signkey_secmod_sig |> finish end module FutureDenom = struct type t = { section_name: string; value: Amount.t; stamp_start: Timestamp.t; stamp_expire_withdraw: Timestamp.t; stamp_expire_deposit: Timestamp.t; stamp_expire_legal: Timestamp.t; denom_pub: DenominationKey.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; denom_secmod_sig: DenominationKeyAnnouncementPS.t; } let jsont = let make section_name value stamp_start stamp_expire_withdraw stamp_expire_deposit stamp_expire_legal denom_pub fee_withdraw fee_deposit fee_refresh fee_refund denom_secmod_sig = { section_name; value; stamp_start; stamp_expire_withdraw; stamp_expire_deposit; stamp_expire_legal; denom_pub; fee_withdraw; fee_deposit; fee_refresh; fee_refund; denom_secmod_sig; } in let section_name t = t.section_name in let value t = t.value in let stamp_start t = t.stamp_start in let stamp_expire_withdraw t = t.stamp_expire_withdraw in let stamp_expire_deposit t = t.stamp_expire_deposit in let stamp_expire_legal t = t.stamp_expire_legal in let denom_pub t = t.denom_pub in let fee_withdraw t = t.fee_withdraw in let fee_deposit t = t.fee_deposit in let fee_refresh t = t.fee_refresh in let fee_refund t = t.fee_refund in let denom_secmod_sig t = t.denom_secmod_sig in map ~kind:"FutureDenom" make |> mem "section_name" Jsont.string ~enc:section_name |> mem "value" Amount.jsont ~enc:value |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_expire_withdraw" Timestamp.jsont ~enc:stamp_expire_withdraw |> mem "stamp_expire_deposit" Timestamp.jsont ~enc:stamp_expire_deposit |> mem "stamp_expire_legal" Timestamp.jsont ~enc:stamp_expire_legal |> mem "denom_pub" DenominationKey.jsont ~enc:denom_pub |> mem "fee_withdraw" Amount.jsont ~enc:fee_withdraw |> mem "fee_deposit" Amount.jsont ~enc:fee_deposit |> mem "fee_refresh" Amount.jsont ~enc:fee_refresh |> mem "fee_refund" Amount.jsont ~enc:fee_refund |> mem "denom_secmod_sig" DenominationKeyAnnouncementPS.jsont ~enc:denom_secmod_sig |> finish end module FutureKeysResponse = struct type t = { future_denoms: FutureDenom.t list; future_signkeys: FutureSignKey.t list; master_pub: EddsaPublicKey.t; denom_secmod_public_key: EddsaPublicKey.t; signkey_secmod_public_key: EddsaPublicKey.t; } let jsont = let make future_denoms future_signkeys master_pub denom_secmod_public_key signkey_secmod_public_key = { future_denoms; future_signkeys; master_pub; denom_secmod_public_key; signkey_secmod_public_key; } in let future_denoms t = t.future_denoms in let future_signkeys t = t.future_signkeys in let master_pub t = t.master_pub in let denom_secmod_public_key t = t.denom_secmod_public_key in let signkey_secmod_public_key t = t.signkey_secmod_public_key in map ~kind:"FutureKeysResponse" make |> mem "future_denoms" (Jsont.list FutureDenom.jsont) ~enc:future_denoms |> mem "future_signkeys" (Jsont.list FutureSignKey.jsont) ~enc:future_signkeys |> mem "master_pub" EddsaPublicKey.jsont ~enc:master_pub |> mem "denom_secmod_public_key" EddsaPublicKey.jsont ~enc:denom_secmod_public_key |> mem "signkey_secmod_public_key" EddsaPublicKey.jsont ~enc:signkey_secmod_public_key |> finish end module SignKeySignature = struct type t = { key: EddsaPublicKey.t; master_sig: ExchangeSigningKeyValidityPS.t; } let jsont = let make key master_sig = { key; master_sig } in let key v = v.key in let master_sig v = v.master_sig in map ~kind:"SignKeySignature" make |> mem "key" EddsaPublicKey.jsont ~enc:key |> mem "master_sig" ExchangeSigningKeyValidityPS.jsont ~enc:master_sig |> finish end module DenomSignature = struct type t = { h_denom_pub: HashCode.t; master_sig: DenominationKeyValidityPS.t; } let jsont = let make h_denom_pub master_sig = { h_denom_pub; master_sig } in let h_denom_pub v = v.h_denom_pub in let master_sig v = v.master_sig in map ~kind:"DenomSignature" make |> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub |> mem "master_sig" DenominationKeyValidityPS.jsont ~enc:master_sig |> finish end module MasterSignatures = struct type t = { denom_sigs: DenomSignature.t list; signkey_sigs: SignKeySignature.t list; } let jsont = let make denom_sigs signkey_sigs = { denom_sigs; signkey_sigs } in let denom_sigs v = v.denom_sigs in let signkey_sigs v = v.signkey_sigs in map ~kind:"MasterSignatures" make |> mem "denom_sigs" (Jsont.list DenomSignature.jsont) ~enc:denom_sigs |> mem "signkey_sigs" (Jsont.list SignKeySignature.jsont) ~enc:signkey_sigs |> finish end module DenomRevocationSignature = struct type t = { master_sig: MasterDenominationKeyRevocationPS.t } let jsont = let make master_sig = { master_sig } in let enc v = v.master_sig in map ~kind:"DenomRevocationSignature" make |> mem "master_sig" MasterDenominationKeyRevocationPS.jsont ~enc |> finish end module SignkeyRevocationSignature = struct type t = { master_sig: MasterSigningKeyRevocationPS.t } let jsont = let make master_sig = { master_sig } in let enc v = v.master_sig in map ~kind:"SignkeyRevocationSignature" make |> mem "master_sig" MasterSigningKeyRevocationPS.jsont ~enc |> finish end module AuditorSetupMessage = struct type t = { auditor_url: string; auditor_name: string; auditor_pub: EddsaPublicKey.t; master_sig: MasterAddAuditorPS.t; (* TODO monotonic time something about using monotonic system time here! *) validity_start: Timestamp.t; } let jsont = let make auditor_url auditor_name auditor_pub master_sig validity_start = { auditor_url; auditor_name; auditor_pub; master_sig; validity_start } in let auditor_url v = v.auditor_url in let auditor_name v = v.auditor_name in let auditor_pub v = v.auditor_pub in let master_sig v = v.master_sig in let validity_start v = v.validity_start in map ~kind:"AuditorSetupMessage" make |> mem "auditor_url" Jsont.string ~enc:auditor_url |> mem "auditor_name" Jsont.string ~enc:auditor_name |> mem "auditor_pub" EddsaPublicKey.jsont ~enc:auditor_pub |> mem "master_sig" MasterAddAuditorPS.jsont ~enc:master_sig |> mem "validity_start" Timestamp.jsont ~enc:validity_start |> finish end module AuditorTeardownMessage = struct type t = { master_sig: MasterDelAuditorPS.t; (* TODO monotonic time *) validity_end: Timestamp.t; } let jsont = let make master_sig validity_end = { master_sig; validity_end } in let master_sig v = v.master_sig in let validity_end v = v.validity_end in map ~kind:"AuditorTeardownMessage" make |> mem "master_sig" MasterDelAuditorPS.jsont ~enc:master_sig |> mem "validity_end" Timestamp.jsont ~enc:validity_end |> finish end module WireFeeSetupMessage = struct type t = { wire_method: string; (* TODO over which struct? Signature using the exchange's offline key with purpose TALER_SIGNATURE_MASTER_WIRE_FEES *) master_sig_wire: MasterWireFeePS.t; fee_start: Amount.t; fee_end: Amount.t; closing_fee: Amount.t; wire_fee: Amount.t; } let jsont = let make wire_method master_sig_wire fee_start fee_end closing_fee wire_fee = { wire_method; master_sig_wire; fee_start; fee_end; closing_fee; wire_fee; } in let wire_method v = v.wire_method in let master_sig_wire v = v.master_sig_wire in let fee_start v = v.fee_start in let fee_end v = v.fee_end in let closing_fee v = v.closing_fee in let wire_fee v = v.wire_fee in map ~kind:"WireFeeSetupMessage" make |> mem "wire_method" Jsont.string ~enc:wire_method |> mem "master_sig_wire" MasterWireFeePS.jsont ~enc:master_sig_wire |> mem "fee_start" Amount.jsont ~enc:fee_start |> mem "fee_end" Amount.jsont ~enc:fee_end |> mem "closing_fee" Amount.jsont ~enc:closing_fee |> mem "wire_fee" Amount.jsont ~enc:wire_fee |> finish end module GlobalFees = struct type t = { start_date: Timestamp.t; end_date: Timestamp.t; history_fee: Amount.t; account_fee: Amount.t; purse_fee: Amount.t; history_expiration: RelativeTime.t; purse_account_limit: int; purse_timeout: RelativeTime.t; (* Signature of TALER_GlobalFeesPS. *) master_sig: GlobalFeesPS.t; } let jsont = let make start_date end_date history_fee account_fee purse_fee history_expiration purse_account_limit purse_timeout master_sig = { start_date; end_date; history_fee; account_fee; purse_fee; history_expiration; purse_account_limit; purse_timeout; master_sig; } in let start_date v = v.start_date in let end_date v = v.end_date in let history_fee v = v.history_fee in let account_fee v = v.account_fee in let purse_fee v = v.purse_fee in let history_expiration v = v.history_expiration in let purse_account_limit v = v.purse_account_limit in let purse_timeout v = v.purse_timeout in let master_sig v = v.master_sig in map ~kind:"GlobalFees" make |> mem "start_date" Timestamp.jsont ~enc:start_date |> mem "end_date" Timestamp.jsont ~enc:end_date |> mem "history_fee" Amount.jsont ~enc:history_fee |> mem "account_fee" Amount.jsont ~enc:account_fee |> mem "purse_fee" Amount.jsont ~enc:purse_fee |> mem "history_expiration" RelativeTime.jsont ~enc:history_expiration |> mem "purse_account_limit" Jsont.int ~enc:purse_account_limit |> mem "purse_timeout" RelativeTime.jsont ~enc:purse_timeout |> mem "master_sig" GlobalFeesPS.jsont ~enc:master_sig |> finish end module WireSetupMessage = struct type t = { payto_uri: string; master_sig_wire: MasterWireDetailsPS.t; master_sig_add: MasterAddWirePS.t; (* TODO monotonic time *) validity_start: Timestamp.t; bank_label: string option; priority: int option; } let jsont = let make payto_uri master_sig_wire master_sig_add validity_start bank_label priority = { payto_uri; master_sig_wire; master_sig_add; validity_start; bank_label; priority; } in let payto_uri v = v.payto_uri in let master_sig_wire v = v.master_sig_wire in let master_sig_add v = v.master_sig_add in let validity_start v = v.validity_start in let bank_label v = v.bank_label in let priority v = v.priority in map ~kind:"WireSetupMessage" make |> mem "payto_uri" Jsont.string ~enc:payto_uri |> mem "master_sig_wire" MasterWireDetailsPS.jsont ~enc:master_sig_wire |> mem "master_sig_add" MasterAddWirePS.jsont ~enc:master_sig_add |> mem "validity_start" Timestamp.jsont ~enc:validity_start |> mem "bank_label" (Jsont.option Jsont.string) ~enc:bank_label |> mem "priority" (Jsont.option Jsont.int) ~enc:priority |> finish end module WireTeardownMessage = struct type t = { payto_uri: string; master_sig_del: MasterDelWirePS.t; (* TODO monotonic time *) validity_end: Timestamp.t; } let jsont = let make payto_uri master_sig_del validity_end = { payto_uri; master_sig_del; validity_end } in let payto_uri v = v.payto_uri in let master_sig_del v = v.master_sig_del in let validity_end v = v.validity_end in map ~kind:"WireTeardownMessage" make |> mem "payto_uri" Jsont.string ~enc:payto_uri |> mem "master_sig_del" MasterDelWirePS.jsont ~enc:master_sig_del |> mem "validity_end" Timestamp.jsont ~enc:validity_end |> finish end module DrainProfitsMessage = struct type t = { debit_account_section: string; credit_payto_uri: string; wtid: B32.t; master_sig: MasterDrainProfitPS.t; date: Timestamp.t; amount: Amount.t; } let jsont = let make debit_account_section credit_payto_uri wtid master_sig date amount = { debit_account_section; credit_payto_uri; wtid; master_sig; date; amount; } in let debit_account_section v = v.debit_account_section in let credit_payto_uri v = v.credit_payto_uri in let wtid v = v.wtid in let master_sig v = v.master_sig in let date v = v.date in let amount v = v.amount in map ~kind:"DrainProfitsMessage" make |> mem "debit_account_section" Jsont.string ~enc:debit_account_section |> mem "credit_payto_uri" Jsont.string ~enc:credit_payto_uri |> mem "wtid" B32.jsont ~enc:wtid |> mem "master_sig" MasterDrainProfitPS.jsont ~enc:master_sig |> mem "date" Timestamp.jsont ~enc:date |> mem "amount" Amount.jsont ~enc:amount |> finish end module AmlOfficerSetup = struct type t = { officer_pub: EddsaPublicKey.t; officer_name: string; is_active: bool; read_only: bool; master_sig: MasterAmlOfficerStatusPS.t; change_date: Timestamp.t; } let jsont = let make officer_pub officer_name is_active read_only master_sig change_date = { officer_pub; officer_name; is_active; read_only; master_sig; change_date; } in let officer_pub v = v.officer_pub in let officer_name v = v.officer_name in let is_active v = v.is_active in let read_only v = v.read_only in let master_sig v = v.master_sig in let change_date v = v.change_date in map ~kind:"AmlOfficerSetup" make |> mem "officer_pub" EddsaPublicKey.jsont ~enc:officer_pub |> mem "officer_name" Jsont.string ~enc:officer_name |> mem "is_active" Jsont.bool ~enc:is_active |> mem "read_only" Jsont.bool ~enc:read_only |> mem "master_sig" MasterAmlOfficerStatusPS.jsont ~enc:master_sig |> mem "change_date" Timestamp.jsont ~enc:change_date |> finish end module ExchangePartnerSetupRequest = struct type t = { partner_base_url: string; partner_pub: EddsaPublicKey.t; wad_frequency: RelativeTime.t; master_sig: PartnerConfigurationPS.t; start_date: Timestamp.t; end_date: Timestamp.t; wad_fee: Amount.t; } let jsont = let make partner_base_url partner_pub wad_frequency master_sig start_date end_date wad_fee = { partner_base_url; partner_pub; wad_frequency; master_sig; start_date; end_date; wad_fee; } in let partner_base_url v = v.partner_base_url in let partner_pub v = v.partner_pub in let wad_frequency v = v.wad_frequency in let master_sig v = v.master_sig in let start_date v = v.start_date in let end_date v = v.end_date in let wad_fee v = v.wad_fee in map ~kind:"ExchangePartnerSetupRequest" make |> mem "partner_base_url" Jsont.string ~enc:partner_base_url |> mem "partner_pub" EddsaPublicKey.jsont ~enc:partner_pub |> mem "wad_frequency" RelativeTime.jsont ~enc:wad_frequency |> mem "master_sig" PartnerConfigurationPS.jsont ~enc:master_sig |> mem "start_date" Timestamp.jsont ~enc:start_date |> mem "end_date" Timestamp.jsont ~enc:end_date |> mem "wad_fee" Amount.jsont ~enc:wad_fee |> finish end (* -- types for /keys -- *) module ExchangePartnerListEntry = struct type t = { partner_base_url: string; partner_master_pub: EddsaPublicKey.t; wad_fee: Amount.t; wad_frequency: RelativeTime.t; start_date: Timestamp.t; end_date: Timestamp.t; master_sig: WadPartnerSignaturePS.t; } let jsont = let make partner_base_url partner_master_pub wad_fee wad_frequency start_date end_date master_sig = { partner_base_url; partner_master_pub; wad_fee; wad_frequency; start_date; end_date; master_sig; } in let partner_base_url v = v.partner_base_url in let partner_master_pub v = v.partner_master_pub in let wad_fee v = v.wad_fee in let wad_frequency v = v.wad_frequency in let start_date v = v.start_date in let end_date v = v.end_date in let master_sig v = v.master_sig in map ~kind:"ExchangePartnerListEntry" make |> mem "partner_base_url" Jsont.string ~enc:partner_base_url |> mem "partner_master_pub" EddsaPublicKey.jsont ~enc:partner_master_pub |> mem "wad_fee" Amount.jsont ~enc:wad_fee |> mem "wad_frequency" RelativeTime.jsont ~enc:wad_frequency |> mem "start_date" Timestamp.jsont ~enc:start_date |> mem "end_date" Timestamp.jsont ~enc:end_date |> mem "master_sig" WadPartnerSignaturePS.jsont ~enc:master_sig |> finish end module AggregateTransferFee = struct type t = { wire_fee: Amount.t; closing_fee: Amount.t; start_date: Timestamp.t; end_date: Timestamp.t; sig_: MasterWireFeePS.t; } let jsont = let make wire_fee closing_fee start_date end_date sig_ = { wire_fee; closing_fee; start_date; end_date; sig_ } in let wire_fee v = v.wire_fee in let closing_fee v = v.closing_fee in let start_date v = v.start_date in let end_date v = v.end_date in let sig_ v = v.sig_ in map ~kind:"AggregateTransferFee" make |> mem "wire_fee" Amount.jsont ~enc:wire_fee |> mem "closing_fee" Amount.jsont ~enc:closing_fee |> mem "start_date" Timestamp.jsont ~enc:start_date |> mem "end_date" Timestamp.jsont ~enc:end_date |> mem "sig" MasterWireFeePS.jsont ~enc:sig_ |> finish end module AuditorDenominationKey = struct type t = { denom_pub_h: HashCode.t; auditor_sig: ExchangeKeyValidityPS.t; } let jsont = let make denom_pub_h auditor_sig = { denom_pub_h; auditor_sig } in let denom_pub_h v = v.denom_pub_h in let auditor_sig v = v.auditor_sig in map ~kind:"AuditorDenominationKey" make |> mem "denom_pub_h" HashCode.jsont ~enc:denom_pub_h |> mem "auditor_sig" ExchangeKeyValidityPS.jsont ~enc:auditor_sig |> finish end module AuditorKeys = struct type t = { auditor_pub: EddsaPublicKey.t; auditor_url: string; auditor_name: string; denomination_keys: AuditorDenominationKey.t list; } let jsont = let make auditor_pub auditor_url auditor_name denomination_keys = { auditor_pub; auditor_url; auditor_name; denomination_keys } in let auditor_pub v = v.auditor_pub in let auditor_url v = v.auditor_url in let auditor_name v = v.auditor_name in let denomination_keys v = v.denomination_keys in map ~kind:"AuditorKeys" make |> mem "auditor_pub" EddsaPublicKey.jsont ~enc:auditor_pub |> mem "auditor_url" Jsont.string ~enc:auditor_url |> mem "auditor_name" Jsont.string ~enc:auditor_name |> mem "denomination_keys" (Jsont.list AuditorDenominationKey.jsont) ~enc:denomination_keys |> finish end module SignKey = struct type t = { key: EddsaPublicKey.t; stamp_start: Timestamp.t; stamp_expire: Timestamp.t; stamp_end: Timestamp.t; master_sig: ExchangeSigningKeyValidityPS.t; } let jsont = let make key stamp_start stamp_expire stamp_end master_sig = { key; stamp_start; stamp_expire; stamp_end; master_sig } in let key v = v.key in let stamp_start v = v.stamp_start in let stamp_expire v = v.stamp_expire in let stamp_end v = v.stamp_end in let master_sig v = v.master_sig in map ~kind:"SignKey" make |> mem "key" EddsaPublicKey.jsont ~enc:key |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_expire" Timestamp.jsont ~enc:stamp_expire |> mem "stamp_end" Timestamp.jsont ~enc:stamp_end |> mem "master_sig" ExchangeSigningKeyValidityPS.jsont ~enc:master_sig |> finish end module RecoupDenoms = struct type t = { h_denom_pub: HashCode.t } let jsont = let make h_denom_pub = { h_denom_pub } in let h_denom_pub v = v.h_denom_pub in map ~kind:"RecoupDenoms" make |> mem "h_denom_pub" HashCode.jsont ~enc:h_denom_pub |> finish end module RsaDenom = struct (* correspond to: ({ rsa_pub: RsaPublicKey;} & DenomCommon) *) type t = { rsa_pub: RsaPublicKey.t; master_sig: DenominationKeyValidityPS.t; stamp_start: Timestamp.t; stamp_expire_withdraw: Timestamp.t; stamp_expire_deposit: Timestamp.t; stamp_expire_legal: Timestamp.t; lost: bool option; } let jsont = let make rsa_pub master_sig stamp_start stamp_expire_withdraw stamp_expire_deposit stamp_expire_legal lost = { rsa_pub; master_sig; stamp_start; stamp_expire_withdraw; stamp_expire_deposit; stamp_expire_legal; lost; } in let rsa_pub v = v.rsa_pub in let master_sig v = v.master_sig in let stamp_start v = v.stamp_start in let stamp_expire_withdraw v = v.stamp_expire_withdraw in let stamp_expire_deposit v = v.stamp_expire_deposit in let stamp_expire_legal v = v.stamp_expire_legal in let lost v = v.lost in map ~kind:"RsaDenom" make |> mem "rsa_pub" RsaPublicKey.jsont ~enc:rsa_pub |> mem "master_sig" DenominationKeyValidityPS.jsont ~enc:master_sig |> mem "stamp_start" Timestamp.jsont ~enc:stamp_start |> mem "stamp_expire_withdraw" Timestamp.jsont ~enc:stamp_expire_withdraw |> mem "stamp_expire_deposit" Timestamp.jsont ~enc:stamp_expire_deposit |> mem "stamp_expire_legal" Timestamp.jsont ~enc:stamp_expire_legal |> mem "lost" (Jsont.option Jsont.bool) ~enc:lost |> finish end module RsaDenomGroup = struct type t = { denoms: RsaDenom.t list; value: Amount.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; } let jsont = let make denoms value fee_withdraw fee_deposit fee_refresh fee_refund = { denoms; value; fee_withdraw; fee_deposit; fee_refresh; fee_refund } in let denoms v = v.denoms in let value v = v.value in let fee_withdraw v = v.fee_withdraw in let fee_deposit v = v.fee_deposit in let fee_refresh v = v.fee_refresh in let fee_refund v = v.fee_refund in map ~kind:"RsaDenomGroup" make |> mem "denoms" (Jsont.list RsaDenom.jsont) ~enc:denoms |> mem "value" Amount.jsont ~enc:value |> mem "fee_withdraw" Amount.jsont ~enc:fee_withdraw |> mem "fee_deposit" Amount.jsont ~enc:fee_deposit |> mem "fee_refresh" Amount.jsont ~enc:fee_refresh |> mem "fee_refund" Amount.jsont ~enc:fee_refund |> finish end module DenomGroup = struct type t = Rsa of RsaDenomGroup.t let of_rsa v = Rsa v let jsont = let rsa = Case.map "RSA" RsaDenomGroup.jsont ~dec:of_rsa in let enc_case = function Rsa v -> Case.value rsa v in let cases = Case.[ make rsa ] in map ~kind:"DenomGroup" Fun.id |> case_mem "cipher" Jsont.string ~enc:Fun.id ~enc_case cases |> finish end module AccountLimit = struct type t = { operation_type: Account_operation.t; timeframe: RelativeTime.t; threshold: Amount.t; soft_limit: bool option; } let jsont = let make operation_type timeframe threshold soft_limit = { operation_type; timeframe; threshold; soft_limit } in let operation_type v = v.operation_type in let timeframe v = v.timeframe in let threshold v = v.threshold in let soft_limit v = v.soft_limit in map ~kind:"AccountLimit" make |> mem "operation_type" Account_operation.jsont ~enc:operation_type |> mem "timeframe" RelativeTime.jsont ~enc:timeframe |> mem "threshold" Amount.jsont ~enc:threshold |> opt_mem "soft_limit" Jsont.bool ~enc:soft_limit |> finish end module ZeroLimitedOperation = struct type t = { operation_type: Account_operation.t } let jsont = let make operation_type = { operation_type } in let operation_type v = v.operation_type in map ~kind:"ZeroLimitedOperation" make |> mem "operation_type" Account_operation.jsont ~enc:operation_type |> finish end module RegexAccountRestriction = struct type t = { payto_regex: string; human_hint: string; (* Map from IETF BCP 47 language tags to localized human hints. *) human_hint_i18n: string option; } let jsont = let make payto_regex human_hint human_hint_i18n = { payto_regex; human_hint; human_hint_i18n } in let payto_regex v = v.payto_regex in let human_hint v = v.human_hint in let human_hint_i18n v = v.human_hint_i18n in map ~kind:"RegexAccountRestriction" make |> mem "payto_regex" Jsont.string ~enc:payto_regex |> mem "human_hint" Jsont.string ~enc:human_hint |> opt_mem "human_hint_i18n" Jsont.string ~enc:human_hint_i18n |> finish end module AccountRestriction = struct type t = | Deny | Regex of RegexAccountRestriction.t let of_regex v = Regex v let of_deny () = Deny let jsont = let regex = Case.map "regex" RegexAccountRestriction.jsont ~dec:of_regex in let deny = Case.map "deny" Jsont.ignore ~dec:of_deny in let enc_case = function | Regex v -> Case.value regex v | Deny -> Case.value deny () in let cases = Case.[ make regex; make deny ] in map ~kind:"AccountRestriction" Fun.id |> case_mem "type" Jsont.string ~enc:Fun.id ~enc_case cases |> finish end module ExchangeWireAccount = struct type t = { payto_uri: string; conversion_url: string option; credit_restrictions: AccountRestriction.t list; debit_restrictions: AccountRestriction.t list; master_sig: MasterWireDetailsPS.t; bank_label: string option; priority: int option; } let jsont = let make payto_uri conversion_url credit_restrictions debit_restrictions master_sig bank_label priority = { payto_uri; conversion_url; credit_restrictions; debit_restrictions; master_sig; bank_label; priority; } in let payto_uri v = v.payto_uri in let conversion_url v = v.conversion_url in let credit_restrictions v = v.credit_restrictions in let debit_restrictions v = v.debit_restrictions in let master_sig v = v.master_sig in let bank_label v = v.bank_label in let priority v = v.priority in map ~kind:"ExchangeWireAccount" make |> mem "payto_uri" Jsont.string ~enc:payto_uri |> opt_mem "conversion_url" Jsont.string ~enc:conversion_url |> mem "credit_restrictions" (Jsont.list AccountRestriction.jsont) ~enc:credit_restrictions |> mem "debit_restrictions" (Jsont.list AccountRestriction.jsont) ~enc:debit_restrictions |> mem "master_sig" MasterWireDetailsPS.jsont ~enc:master_sig |> opt_mem "bank_label" Jsont.string ~enc:bank_label |> opt_mem "priority" Jsont.int ~enc:priority |> finish end module ExtensionManifest = struct type t = { critical: bool; version: string; config: Jsont.json option; } let jsont = let make critical version config = { critical; version; config } in let critical v = v.critical in let version v = v.version in let config v = v.config in map ~kind:"ExtensionManifest" make |> mem "critical" Jsont.bool ~enc:critical |> mem "version" Jsont.string ~enc:version |> opt_mem "config" (Jsont.any ()) ~enc:config |> finish end module ExchangeKeysResponse = struct module String_map = Map.Make (String) type t = { version: string; base_url: string; currency: string; shopping_url: string option; open_banking_gateway: string option; bank_compliance_language: string option; currency_specification: CurrencySpecification.t; tiny_amount: Amount.t option; stefan_abs: Amount.t; stefan_log: Amount.t; stefan_lin: Float.t; asset_type: string; accounts: ExchangeWireAccount.t list; wire_fees: AggregateTransferFee.t list Stdlib.Map.Make(Stdlib.String).t; wads: ExchangePartnerListEntry.t list; rewards_allowed: bool; kyc_enabled: bool; disable_direct_deposit: bool; master_public_key: EddsaPublicKey.t; reserve_closing_delay: RelativeTime.t; wallet_balance_limit_without_kyc: Amount.t list option; hard_limits: AccountLimit.t list; zero_limits: ZeroLimitedOperation.t list; denominations: DenomGroup.t list; (* Compact EdDSA signature (binary-only) over the contatentation of all of the master_sigs (in reverse chronological order by group) in the arrays under "denominations" *) exchange_sig: ExchangeKeySetPS.t; exchange_pub: EddsaPublicKey.t; recoup: RecoupDenoms.t list; global_fees: GlobalFees.t list; list_issue_date: Timestamp.t; auditors: AuditorKeys.t list; signkeys: SignKey.t list; extensions: ExtensionManifest.t Stdlib.Map.Make(Stdlib.String).t option; (* Signature by the exchange master key of the SHA-256 hash of the normalized JSON-object of field extensions, if it was set. The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. *) extensions_sig: EddsaSignature.t option; } let jsont = let make version base_url currency shopping_url open_banking_gateway bank_compliance_language currency_specification tiny_amount stefan_abs stefan_log stefan_lin asset_type accounts wire_fees wads rewards_allowed kyc_enabled disable_direct_deposit master_public_key reserve_closing_delay wallet_balance_limit_without_kyc hard_limits zero_limits denominations exchange_sig exchange_pub recoup global_fees list_issue_date auditors signkeys extensions extensions_sig = { version; base_url; currency; shopping_url; open_banking_gateway; bank_compliance_language; currency_specification; tiny_amount; stefan_abs; stefan_log; stefan_lin; asset_type; accounts; wire_fees; wads; rewards_allowed; kyc_enabled; disable_direct_deposit; master_public_key; reserve_closing_delay; wallet_balance_limit_without_kyc; hard_limits; zero_limits; denominations; exchange_sig; exchange_pub; recoup; global_fees; list_issue_date; auditors; signkeys; extensions; extensions_sig; } in let version v = v.version in let base_url v = v.base_url in let currency v = v.currency in let shopping_url v = v.shopping_url in let open_banking_gateway v = v.open_banking_gateway in let bank_compliance_language v = v.bank_compliance_language in let currency_specification v = v.currency_specification in let tiny_amount v = v.tiny_amount in let stefan_abs v = v.stefan_abs in let stefan_log v = v.stefan_log in let stefan_lin v = v.stefan_lin in let asset_type v = v.asset_type in let accounts v = v.accounts in let wire_fees v = v.wire_fees in let wads v = v.wads in let rewards_allowed v = v.rewards_allowed in let kyc_enabled v = v.kyc_enabled in let disable_direct_deposit v = v.disable_direct_deposit in let master_public_key v = v.master_public_key in let reserve_closing_delay v = v.reserve_closing_delay in let wallet_balance_limit_without_kyc v = v.wallet_balance_limit_without_kyc in let hard_limits v = v.hard_limits in let zero_limits v = v.zero_limits in let denominations v = v.denominations in let exchange_sig v = v.exchange_sig in let exchange_pub v = v.exchange_pub in let recoup v = v.recoup in let global_fees v = v.global_fees in let list_issue_date v = v.list_issue_date in let auditors v = v.auditors in let signkeys v = v.signkeys in let extensions v = v.extensions in let extensions_sig v = v.extensions_sig in map ~kind:"ExchangeKeysResponse" make |> mem "version" Jsont.string ~enc:version |> mem "base_url" Jsont.string ~enc:base_url |> mem "currency" Jsont.string ~enc:currency |> opt_mem "shopping_url" Jsont.string ~enc:shopping_url |> opt_mem "open_banking_gateway" Jsont.string ~enc:open_banking_gateway |> opt_mem "bank_compliance_language" Jsont.string ~enc:bank_compliance_language |> mem "currency_specification" CurrencySpecification.jsont ~enc:currency_specification |> opt_mem "tiny_amount" Amount.jsont ~enc:tiny_amount |> mem "stefan_abs" Amount.jsont ~enc:stefan_abs |> mem "stefan_log" Amount.jsont ~enc:stefan_log |> mem "stefan_lin" Jsont.number ~enc:stefan_lin |> mem "asset_type" Jsont.string ~enc:asset_type |> mem "accounts" (Jsont.list ExchangeWireAccount.jsont) ~enc:accounts |> mem "wire_fees" (Jsont.Object.as_string_map (Jsont.list AggregateTransferFee.jsont)) ~enc:wire_fees |> mem "wads" (Jsont.list ExchangePartnerListEntry.jsont) ~enc:wads |> mem "rewards_allowed" Jsont.bool ~enc:rewards_allowed |> mem "kyc_enabled" Jsont.bool ~enc:kyc_enabled |> mem "disable_direct_deposit" Jsont.bool ~enc:disable_direct_deposit |> mem "master_public_key" EddsaPublicKey.jsont ~enc:master_public_key |> mem "reserve_closing_delay" RelativeTime.jsont ~enc:reserve_closing_delay |> opt_mem "wallet_balance_limit_without_kyc" (Jsont.list Amount.jsont) ~enc:wallet_balance_limit_without_kyc |> mem "hard_limits" (Jsont.list AccountLimit.jsont) ~enc:hard_limits |> mem "zero_limits" (Jsont.list ZeroLimitedOperation.jsont) ~enc:zero_limits |> mem "denominations" (Jsont.list DenomGroup.jsont) ~enc:denominations |> mem "exchange_sig" ExchangeKeySetPS.jsont ~enc:exchange_sig |> mem "exchange_pub" EddsaPublicKey.jsont ~enc:exchange_pub |> mem "recoup" (Jsont.list RecoupDenoms.jsont) ~enc:recoup |> mem "global_fees" (Jsont.list GlobalFees.jsont) ~enc:global_fees |> mem "list_issue_date" Timestamp.jsont ~enc:list_issue_date |> mem "auditors" (Jsont.list AuditorKeys.jsont) ~enc:auditors |> mem "signkeys" (Jsont.list SignKey.jsont) ~enc:signkeys |> opt_mem "extensions" (Jsont.Object.as_string_map ExtensionManifest.jsont) ~enc:extensions |> opt_mem "extensions_sig" EddsaSignature.jsont ~enc:extensions_sig |> finish end