(* 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" use of _monotonic_ time option: correct use opt_mem or Jsont.option better types: - payto_uri - uri 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_sig 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 DenominationHash = Bin_type.DenominationHash 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 module B32 = struct include B32 let jsont = Jsont.of_of_string ~kind:"B32" B32.decode ~enc:B32.encode let caqti = Caqti_type.custom ~encode:(fun v -> Ok (B32.encode v)) ~decode:B32.decode Caqti_type.string 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; detail: string option; parameter: string option; path: string option; offset: string option; index: string option; object_: string option; currency: string option; type_expected: string option; type_actual: string option; extra: Jsont.json option; } let make code hint detail parameter path offset index object_ currency type_expected type_actual extra = { code; hint; detail; parameter; path; offset; index; object_; currency; type_expected; type_actual; extra; } let jsont = let code v = v.code in let hint v = v.hint in let detail v = v.detail in let parameter v = v.parameter in let path v = v.path in let offset v = v.offset in let index v = v.index in let object_ v = v.object_ in let currency v = v.currency in let type_expected v = v.type_expected in let type_actual v = v.type_actual in let extra v = v.extra in let open Jsont.Object in map ~kind:"ErrorDetail" make |> mem "code" Jsont.int ~enc:code |> opt_mem "hint" Jsont.string ~enc:hint |> opt_mem "detail" Jsont.string ~enc:detail |> opt_mem "parameter" Jsont.string ~enc:parameter |> opt_mem "path" Jsont.string ~enc:path |> opt_mem "offset" Jsont.string ~enc:offset |> opt_mem "index" Jsont.string ~enc:index |> opt_mem "object" Jsont.string ~enc:object_ |> opt_mem "currency" Jsont.string ~enc:currency |> opt_mem "type_expected" Jsont.string ~enc:type_expected |> opt_mem "type_actual" Jsont.string ~enc:type_actual |> opt_mem "extra" (Jsont.any ()) ~enc:extra |> finish let make ?hint ?detail ?parameter ?path ?offset ?index ?object_ ?currency ?type_expected ?type_actual ?extra code = make code hint detail parameter path offset index object_ currency type_expected type_actual extra 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 DenominationKey = struct type t = Rsa of RsaDenominationKey.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" zero ~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: SigningKeyAnnouncement.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" SigningKeyAnnouncement.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: DenominationKeyAnnouncement.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" DenominationKeyAnnouncement.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: ExchangeSigningKeyValidity.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" ExchangeSigningKeyValidity.jsont ~enc:master_sig |> finish end module DenomSignature = struct type t = { h_denom_pub: DenominationHash.t; master_sig: DenominationKeyValidity.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" DenominationHash.jsont ~enc:h_denom_pub |> mem "master_sig" DenominationKeyValidity.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: MasterDenominationKeyRevocation.t } let jsont = let make master_sig = { master_sig } in let enc v = v.master_sig in map ~kind:"DenomRevocationSignature" make |> mem "master_sig" MasterDenominationKeyRevocation.jsont ~enc |> finish end module SignkeyRevocationSignature = struct type t = { master_sig: MasterSigningKeyRevocation.t } let jsont = let make master_sig = { master_sig } in let enc v = v.master_sig in map ~kind:"SignkeyRevocationSignature" make |> mem "master_sig" MasterSigningKeyRevocation.jsont ~enc |> finish end module AuditorSetupMessage = struct type t = { auditor_url: string; auditor_name: string; auditor_pub: EddsaPublicKey.t; master_sig: MasterAddAuditor.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" MasterAddAuditor.jsont ~enc:master_sig |> mem "validity_start" Timestamp.jsont ~enc:validity_start |> finish end module AuditorTeardownMessage = struct type t = { master_sig: MasterDelAuditor.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" MasterDelAuditor.jsont ~enc:master_sig |> mem "validity_end" Timestamp.jsont ~enc:validity_end |> finish end module WireFeeSetupMessage = struct type t = { wire_method: string; master_sig_wire: MasterWireFee.t; fee_start: Timestamp.t; fee_end: Timestamp.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" MasterWireFee.jsont ~enc:master_sig_wire |> mem "fee_start" Timestamp.jsont ~enc:fee_start |> mem "fee_end" Timestamp.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: Time.Relative.t; purse_account_limit: int32; purse_timeout: Time.Relative.t; master_sig: GlobalFees.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" Time.Relative.jsont ~enc:history_expiration |> mem "purse_account_limit" Jsont.int32 ~enc:purse_account_limit |> mem "purse_timeout" Time.Relative.jsont ~enc:purse_timeout |> mem "master_sig" GlobalFees.jsont ~enc:master_sig |> finish end module WireSetupMessage = struct type t = { payto_uri: string; master_sig_wire: MasterWireDetails.t; master_sig_add: MasterAddWire.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" MasterWireDetails.jsont ~enc:master_sig_wire |> mem "master_sig_add" MasterAddWire.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: MasterDelWire.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" MasterDelWire.jsont ~enc:master_sig_del |> mem "validity_end" Timestamp.jsont ~enc:validity_end |> finish end module DrainProfitsMessage = struct type t = { wtid: B32.t; debit_account_section: string; credit_payto_uri: string; date: Timestamp.t; amount: Amount.t; master_sig: MasterDrainProfit.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" MasterDrainProfit.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; master_sig: MasterAmlOfficerStatus.t; officer_name: string; is_active: bool; read_only: bool; 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" MasterAmlOfficerStatus.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: Time.Relative.t; master_sig: PartnerConfiguration.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" Time.Relative.jsont ~enc:wad_frequency |> mem "master_sig" PartnerConfiguration.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: Time.Relative.t; start_date: Timestamp.t; end_date: Timestamp.t; master_sig: WadPartnerSignature.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" Time.Relative.jsont ~enc:wad_frequency |> mem "start_date" Timestamp.jsont ~enc:start_date |> mem "end_date" Timestamp.jsont ~enc:end_date |> mem "master_sig" WadPartnerSignature.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_: MasterWireFee.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" MasterWireFee.jsont ~enc:sig_ |> finish end module AuditorDenominationKey = struct type t = { denom_pub_h: DenominationHash.t; auditor_sig: ExchangeKeyValidity.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" DenominationHash.jsont ~enc:denom_pub_h |> mem "auditor_sig" ExchangeKeyValidity.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: ExchangeSigningKeyValidity.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" ExchangeSigningKeyValidity.jsont ~enc:master_sig |> finish end module RecoupDenoms = struct type t = { h_denom_pub: DenominationHash.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" DenominationHash.jsont ~enc:h_denom_pub |> finish end module RsaDenom = struct (* correspond to: ({ rsa_pub: RsaPublicKey;} & DenomCommon) *) type t = { rsa_pub: RsaPublicKey.t; master_sig: DenominationKeyValidity.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" DenominationKeyValidity.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 of_cs _v = Jsont.Error.msg Jsont.Meta.none "CSDenomGroup are not supported" let of_rsa_age_restricted _v = Jsont.Error.msg Jsont.Meta.none "DenomGroupRsaAgeRestricted are not supported" let jsont = let rsa = Case.map "RSA" RsaDenomGroup.jsont ~dec:of_rsa in let cs = Case.map "CS" zero ~dec:of_cs in let rsa_age_restricted = Case.map "RSA+age_restricted" zero ~dec:of_rsa_age_restricted in let cs_age_restricted = Case.map "CS+age_restricted" zero ~dec:of_cs in let enc_case = function Rsa v -> Case.value rsa v in let cases = Case. [ make rsa; make cs; make rsa_age_restricted; make cs_age_restricted ] 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: Time.Relative.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" Time.Relative.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" zero ~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: MasterWireDetails.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" MasterWireDetails.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: Time.Relative.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: ExchangeKeySet.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" Time.Relative.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" ExchangeKeySet.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