2025-12-21 19:32:54 +01:00
|
|
|
(* this module defines caqti encoding/decodings *)
|
2026-02-05 17:51:24 +01:00
|
|
|
open Caqti_type
|
2025-12-21 19:32:54 +01:00
|
|
|
open Crypto
|
|
|
|
|
open Api
|
|
|
|
|
|
2025-12-21 22:13:35 +01:00
|
|
|
(* TODO
|
|
|
|
|
check that we use Caqti_type.octets for binary data *)
|
|
|
|
|
|
2025-12-21 19:32:54 +01:00
|
|
|
let amount : Amount.t t =
|
|
|
|
|
let open Amount in
|
|
|
|
|
custom
|
|
|
|
|
~encode:(fun amount -> Ok (amount.value, amount.fraction))
|
|
|
|
|
~decode:(fun (value, fraction) ->
|
|
|
|
|
Amount.make ~sign:None ~currency:Config.currency ~value ~fraction)
|
|
|
|
|
(t2 int64 int32)
|
|
|
|
|
|
|
|
|
|
(* we want to use int64 timestamps,
|
|
|
|
|
not postgresql built-in timestamp type *)
|
2026-02-05 15:31:49 +01:00
|
|
|
let ptime : unit t = Caqti_type.unit
|
2025-12-21 19:32:54 +01:00
|
|
|
let time = Timestamp.caqti
|
2026-02-05 15:31:49 +01:00
|
|
|
let time_span = Time.Relative.caqti
|
2025-12-21 19:32:54 +01:00
|
|
|
let age_mask : int t = Caqti_type.int
|
|
|
|
|
let rsa_pub = RsaPublicKey.caqti
|
|
|
|
|
let eddsa_pub = EddsaPublicKey.caqti
|
|
|
|
|
let eddsa_sig = EddsaSignature.caqti
|
|
|
|
|
|
|
|
|
|
(* todo: enum type for wire_method? *)
|
|
|
|
|
let wire_method = Caqti_type.string
|
|
|
|
|
let payto_uri = Caqti_type.string
|
2025-12-21 22:13:35 +01:00
|
|
|
let b32 = B32.caqti
|
2025-12-21 19:32:54 +01:00
|
|
|
|
|
|
|
|
include struct
|
|
|
|
|
(* alias for hash *)
|
2026-02-05 17:51:24 +01:00
|
|
|
open Hash
|
2025-12-21 19:32:54 +01:00
|
|
|
|
|
|
|
|
let fullpayto_hash = FullPaytoHash.caqti
|
|
|
|
|
let nomalizaedpayto_hash = NormalizedPaytoHash.caqti
|
|
|
|
|
let denomination_hash = DenominationHash.caqti
|
|
|
|
|
let privatecontract_hash = PrivateContractHash.caqti
|
|
|
|
|
let extensionspolicy_hash = ExtensionsPolicyHash.caqti
|
|
|
|
|
let merchantwire_hash = MerchantWireHash.caqti
|
|
|
|
|
let agecommitment_hash = AgeCommitmentHash.caqti
|
|
|
|
|
let blindedcoin_hash = BlindedCoinHash.caqti
|
|
|
|
|
let coinpub_hash = CoinPubHash.caqti
|
|
|
|
|
let outputcommitment_hash = OutputCommitmentHash.caqti
|
|
|
|
|
let planchets_hash = HashPlanchetsP.caqti
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let signkey_data =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.ExchangeSigningKeyValidity.caqti in
|
|
|
|
|
let revoked_sig = option Signatures.MasterSigningKeyRevocation.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
custom
|
|
|
|
|
~encode:(fun
|
2025-12-21 20:06:01 +01:00
|
|
|
Signkey_data.
|
2025-12-21 20:52:59 +01:00
|
|
|
{ pub; stamp_start; stamp_expire; stamp_end; master_sig; revoked_sig }
|
2025-12-21 19:32:54 +01:00
|
|
|
->
|
|
|
|
|
match master_sig with
|
|
|
|
|
| None -> Error "signkey_data master_sig is none"
|
|
|
|
|
| Some master_sig ->
|
2025-12-21 20:52:59 +01:00
|
|
|
Ok (pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
(pub, stamp_start, stamp_expire, stamp_end, master_sig, revoked_sig) ->
|
2025-12-21 19:32:54 +01:00
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
pub;
|
|
|
|
|
stamp_start;
|
|
|
|
|
stamp_expire;
|
|
|
|
|
stamp_end;
|
|
|
|
|
master_sig= Some master_sig;
|
2025-12-21 20:52:59 +01:00
|
|
|
revoked_sig;
|
2025-12-21 19:32:54 +01:00
|
|
|
})
|
2025-12-21 20:52:59 +01:00
|
|
|
(t6 eddsa_pub time time time master_sig revoked_sig)
|
2025-12-21 19:32:54 +01:00
|
|
|
|
|
|
|
|
let denom_data =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.DenominationKeyValidity.caqti in
|
|
|
|
|
let revoked_sig = option Signatures.MasterDenominationKeyRevocation.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
Denom_data.
|
|
|
|
|
{
|
|
|
|
|
pub;
|
|
|
|
|
value;
|
|
|
|
|
stamp_start;
|
|
|
|
|
stamp_expire_withdraw;
|
|
|
|
|
stamp_expire_deposit;
|
|
|
|
|
stamp_expire_legal;
|
|
|
|
|
fee_withdraw;
|
|
|
|
|
fee_deposit;
|
|
|
|
|
fee_refresh;
|
|
|
|
|
fee_refund;
|
|
|
|
|
age_mask;
|
|
|
|
|
h_pub;
|
|
|
|
|
master_sig;
|
2025-12-21 20:52:59 +01:00
|
|
|
revoked_sig;
|
2025-12-21 19:32:54 +01:00
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
match master_sig with
|
|
|
|
|
| None -> Error "denom_data master_sig is none"
|
|
|
|
|
| Some master_sig ->
|
|
|
|
|
Ok
|
|
|
|
|
( pub,
|
|
|
|
|
value,
|
|
|
|
|
stamp_start,
|
|
|
|
|
stamp_expire_withdraw,
|
|
|
|
|
stamp_expire_deposit,
|
|
|
|
|
stamp_expire_legal,
|
|
|
|
|
fee_withdraw,
|
|
|
|
|
fee_deposit,
|
|
|
|
|
fee_refresh,
|
|
|
|
|
fee_refund,
|
|
|
|
|
age_mask,
|
2025-12-21 20:52:59 +01:00
|
|
|
(h_pub, master_sig, revoked_sig) ))
|
2025-12-21 19:32:54 +01:00
|
|
|
~decode:(fun
|
|
|
|
|
( pub,
|
|
|
|
|
value,
|
|
|
|
|
stamp_start,
|
|
|
|
|
stamp_expire_withdraw,
|
|
|
|
|
stamp_expire_deposit,
|
|
|
|
|
stamp_expire_legal,
|
|
|
|
|
fee_withdraw,
|
|
|
|
|
fee_deposit,
|
|
|
|
|
fee_refresh,
|
|
|
|
|
fee_refund,
|
|
|
|
|
age_mask,
|
2025-12-21 20:52:59 +01:00
|
|
|
(h_pub, master_sig, revoked_sig) )
|
2025-12-21 19:32:54 +01:00
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
pub;
|
|
|
|
|
value;
|
|
|
|
|
stamp_start;
|
|
|
|
|
stamp_expire_withdraw;
|
|
|
|
|
stamp_expire_deposit;
|
|
|
|
|
stamp_expire_legal;
|
|
|
|
|
fee_withdraw;
|
|
|
|
|
fee_deposit;
|
|
|
|
|
fee_refresh;
|
|
|
|
|
fee_refund;
|
|
|
|
|
age_mask;
|
|
|
|
|
h_pub;
|
|
|
|
|
master_sig= Some master_sig;
|
2025-12-21 20:52:59 +01:00
|
|
|
revoked_sig;
|
2025-12-21 19:32:54 +01:00
|
|
|
})
|
|
|
|
|
(t12 rsa_pub amount time time time time amount amount amount amount int
|
2025-12-21 20:52:59 +01:00
|
|
|
(t3 denomination_hash master_sig revoked_sig))
|
2025-12-21 19:32:54 +01:00
|
|
|
|
|
|
|
|
let account_restrictions =
|
|
|
|
|
custom
|
|
|
|
|
~encode:(fun l -> Api.encode (Jsont.list AccountRestriction.jsont) l)
|
|
|
|
|
~decode:(fun s -> Api.decode (Jsont.list AccountRestriction.jsont) s)
|
|
|
|
|
string
|
|
|
|
|
|
|
|
|
|
let global_fee =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.GlobalFees.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
GlobalFees.
|
|
|
|
|
{
|
|
|
|
|
start_date;
|
|
|
|
|
end_date;
|
|
|
|
|
history_fee;
|
|
|
|
|
account_fee;
|
|
|
|
|
purse_fee;
|
|
|
|
|
history_expiration;
|
|
|
|
|
purse_account_limit;
|
|
|
|
|
purse_timeout;
|
|
|
|
|
master_sig;
|
|
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
( start_date,
|
|
|
|
|
end_date,
|
|
|
|
|
history_fee,
|
|
|
|
|
account_fee,
|
|
|
|
|
purse_fee,
|
|
|
|
|
history_expiration,
|
|
|
|
|
purse_account_limit,
|
|
|
|
|
purse_timeout,
|
|
|
|
|
master_sig ))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
( start_date,
|
|
|
|
|
end_date,
|
|
|
|
|
history_fee,
|
|
|
|
|
account_fee,
|
|
|
|
|
purse_fee,
|
|
|
|
|
history_expiration,
|
|
|
|
|
purse_account_limit,
|
|
|
|
|
purse_timeout,
|
|
|
|
|
master_sig )
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
start_date;
|
|
|
|
|
end_date;
|
|
|
|
|
history_fee;
|
|
|
|
|
account_fee;
|
|
|
|
|
purse_fee;
|
|
|
|
|
history_expiration;
|
|
|
|
|
purse_account_limit;
|
|
|
|
|
purse_timeout;
|
|
|
|
|
master_sig;
|
|
|
|
|
})
|
|
|
|
|
Caqti_type.(
|
|
|
|
|
t9 time time amount amount amount time_span int32 time_span master_sig)
|
|
|
|
|
|
|
|
|
|
let aggregate_transfer_fee =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.MasterWireFee.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
Caqti_type.custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
AggregateTransferFee.
|
|
|
|
|
{ wire_fee; closing_fee; start_date; end_date; sig_ }
|
|
|
|
|
-> Ok (wire_fee, closing_fee, start_date, end_date, sig_))
|
|
|
|
|
~decode:(fun (wire_fee, closing_fee, start_date, end_date, sig_) ->
|
|
|
|
|
Ok
|
|
|
|
|
AggregateTransferFee.
|
|
|
|
|
{ wire_fee; closing_fee; start_date; end_date; sig_ })
|
|
|
|
|
Caqti_type.(t5 amount amount time time master_sig)
|
|
|
|
|
|
|
|
|
|
let exchange_wire_account =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.MasterWireDetails.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
Caqti_type.custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
ExchangeWireAccount.
|
|
|
|
|
{
|
|
|
|
|
payto_uri;
|
|
|
|
|
conversion_url;
|
|
|
|
|
debit_restrictions;
|
|
|
|
|
credit_restrictions;
|
|
|
|
|
master_sig;
|
|
|
|
|
bank_label;
|
|
|
|
|
priority;
|
|
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
( payto_uri,
|
|
|
|
|
conversion_url,
|
|
|
|
|
debit_restrictions,
|
|
|
|
|
credit_restrictions,
|
|
|
|
|
master_sig,
|
|
|
|
|
bank_label,
|
|
|
|
|
priority ))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
( payto_uri,
|
|
|
|
|
conversion_url,
|
|
|
|
|
debit_restrictions,
|
|
|
|
|
credit_restrictions,
|
|
|
|
|
master_sig,
|
|
|
|
|
bank_label,
|
|
|
|
|
priority )
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
payto_uri;
|
|
|
|
|
conversion_url;
|
|
|
|
|
debit_restrictions;
|
|
|
|
|
credit_restrictions;
|
|
|
|
|
master_sig;
|
|
|
|
|
bank_label;
|
|
|
|
|
priority;
|
|
|
|
|
})
|
|
|
|
|
Caqti_type.(
|
|
|
|
|
t7 payto_uri (option string) account_restrictions account_restrictions
|
|
|
|
|
master_sig (option string) (option int))
|
|
|
|
|
|
|
|
|
|
let drain_profit_message =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.MasterDrainProfit.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
Caqti_type.custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
DrainProfitsMessage.
|
|
|
|
|
{
|
|
|
|
|
wtid;
|
|
|
|
|
debit_account_section;
|
|
|
|
|
credit_payto_uri;
|
|
|
|
|
date;
|
|
|
|
|
amount;
|
|
|
|
|
master_sig;
|
|
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
(wtid, debit_account_section, credit_payto_uri, date, amount, master_sig))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
(wtid, debit_account_section, credit_payto_uri, date, amount, master_sig)
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
wtid;
|
|
|
|
|
debit_account_section;
|
|
|
|
|
credit_payto_uri;
|
|
|
|
|
date;
|
|
|
|
|
amount;
|
|
|
|
|
master_sig;
|
|
|
|
|
})
|
|
|
|
|
Caqti_type.(t6 b32 string string time amount master_sig)
|
|
|
|
|
|
|
|
|
|
let aml_officer_setup =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.MasterAmlOfficerStatus.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
Caqti_type.custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
AmlOfficerSetup.
|
|
|
|
|
{
|
|
|
|
|
officer_pub;
|
|
|
|
|
master_sig;
|
|
|
|
|
officer_name;
|
|
|
|
|
is_active;
|
|
|
|
|
read_only;
|
|
|
|
|
change_date;
|
|
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
( officer_pub,
|
|
|
|
|
master_sig,
|
|
|
|
|
officer_name,
|
|
|
|
|
is_active,
|
|
|
|
|
read_only,
|
|
|
|
|
change_date ))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
( officer_pub,
|
|
|
|
|
master_sig,
|
|
|
|
|
officer_name,
|
|
|
|
|
is_active,
|
|
|
|
|
read_only,
|
|
|
|
|
change_date )
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
officer_pub;
|
|
|
|
|
master_sig;
|
|
|
|
|
officer_name;
|
|
|
|
|
is_active;
|
|
|
|
|
read_only;
|
|
|
|
|
change_date;
|
|
|
|
|
})
|
|
|
|
|
Caqti_type.(t6 eddsa_pub master_sig string bool bool time)
|
|
|
|
|
|
|
|
|
|
let exchange_partner_setup =
|
2026-02-05 19:26:59 +01:00
|
|
|
let master_sig = Signatures.PartnerConfiguration.caqti in
|
2025-12-21 19:32:54 +01:00
|
|
|
Caqti_type.custom
|
|
|
|
|
~encode:(fun
|
|
|
|
|
ExchangePartnerSetupRequest.
|
|
|
|
|
{
|
|
|
|
|
partner_pub;
|
|
|
|
|
start_date;
|
|
|
|
|
end_date;
|
|
|
|
|
wad_frequency;
|
|
|
|
|
wad_fee;
|
|
|
|
|
master_sig;
|
|
|
|
|
partner_base_url;
|
|
|
|
|
}
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
( partner_pub,
|
|
|
|
|
start_date,
|
|
|
|
|
end_date,
|
|
|
|
|
wad_frequency,
|
|
|
|
|
wad_fee,
|
|
|
|
|
master_sig,
|
|
|
|
|
partner_base_url ))
|
|
|
|
|
~decode:(fun
|
|
|
|
|
( partner_pub,
|
|
|
|
|
start_date,
|
|
|
|
|
end_date,
|
|
|
|
|
wad_frequency,
|
|
|
|
|
wad_fee,
|
|
|
|
|
master_sig,
|
|
|
|
|
partner_base_url )
|
|
|
|
|
->
|
|
|
|
|
Ok
|
|
|
|
|
{
|
|
|
|
|
partner_base_url;
|
|
|
|
|
partner_pub;
|
|
|
|
|
wad_frequency;
|
|
|
|
|
master_sig;
|
|
|
|
|
start_date;
|
|
|
|
|
end_date;
|
|
|
|
|
wad_fee;
|
|
|
|
|
})
|
|
|
|
|
Caqti_type.(t7 eddsa_pub time time time_span amount master_sig string)
|