123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)typemeth=[`GET|`POST|`DELETE|`PUT|`PATCH]letstring_of_meth=Resto.string_of_methletmeth_of_string=Resto.meth_of_stringletmeth_encoding=letopenData_encodinginconvstring_of_meth(funm->matchmeth_of_stringmwith|None->Stdlib.failwith"Cannot parse methods"|Somes->s)stringmoduleMethMap=Resto.MethMaptype(+'m,'pr,'p,'q,'i,'o,'e)raw=('m,'pr,'p,'q,'i,'o,'e)Resto.MakeService(RPC_encoding).tconstraint'meth=[<meth]typeerror=Error_monad.errorlisttype(+'meth,'prefix,'params,'query,'input,'output)t=('meth,'prefix,'params,'query,'input,'output,error)rawconstraint'meth=[<meth]type(+'meth,'prefix,'params,'query,'input,'output)service=('meth,'prefix,'params,'query,'input,'output,error)rawconstraint'meth=[<meth]include(Resto.MakeService(RPC_encoding):moduletypeofstructincludeResto.MakeService(RPC_encoding)endwithtype(+'m,'pr,'p,'q,'i,'o,'e)t:=('m,'pr,'p,'q,'i,'o,'e)rawandtype(+'m,'pr,'p,'q,'i,'o,'e)service:=('m,'pr,'p,'q,'i,'o,'e)raw)leterror_path=refNonetypeError_monad.error+=Unparsable_RPC_errorofData_encoding.jsontypeError_monad.error+=Empty_error_listlet()=letopenError_monadinregister_error_kind`Branch~id:"RPC.Unexpected_error_encoding"~title:"RPC fails with an unparsable error message"~description:"The RPC returned with an error code, and the associated body was not a \
valid error trace. It is likely that the answer does not comes directly \
from a compatible node."~pp:(funppfmsg->Format.fprintfppf"@[<v 2>The RPC returned with an error code, and the associated body \
was not a valid error trace:@[%a@]@ It is likely that the answer does \
not comes directly from a compatible node.@]@."Data_encoding.Json.ppmsg)Data_encoding.(obj1(req"unparsable message"json))(functionUnparsable_RPC_errormsg->Somemsg|_->None)(funmsg->Unparsable_RPC_errormsg)let()=letopenError_monadinregister_error_kind`Branch~id:"RPC.Empty_error_list"~title:"RPC returned an empty list of errors"~description:"The RPC returned with an error code but no associated error."~pp:(funppf()->Format.fprintfppf"@[<v 2>The RPC returned with an error code but no associated \
error.@]@.")Data_encoding.empty(functionEmpty_error_list->Some()|_->None)(fun()->Empty_error_list)leterror_encoding=letopenData_encodingindelayed(fun()->let{meth;uri;_}=match!error_pathwithNone->assertfalse|Somep->pindef"error"~description:(Printf.sprintf"The full list of errors is available with the global RPC `%s %s`"(string_of_methmeth)(Uri.path_and_queryuri))@@conv~schema:Json_schema.any(funerrors->`A(List.mapError_monad.json_of_errorerrors))(function|`A[]|`O[]->[Empty_error_list]|json->((* in BSON, which is used as an intermediate step when
serialising in binary, [`A _] and [`O _] are
indistinguishable. For this reason, we set [bson_relaxation]
when destructing the JSON. *)matchJson.destruct~bson_relaxation:trueError_monad.trace_encodingjsonwith|[]->assertfalse(* see [`A [] | `O []] above *)|trace->trace|exceptionJson.Cannot_destruct_->[Unparsable_RPC_errorjson]))json)leterror_opt_encoding=letopenData_encodingindelayed(fun()->let{meth;uri;_}=match!error_pathwithNone->assertfalse|Somep->pindef"error_opt"~description:(Printf.sprintf"An optional error-trace (None indicates no error). The full list \
of errors is available with the global RPC `%s %s`"(string_of_methmeth)(Uri.path_and_queryuri))@@conv~schema:Json_schema.any(function|None|Some[]->`Null|Some(_::_aserrors)->`A(List.mapError_monad.json_of_errorerrors))(function|`Null|`A[]|`O[]->None|json->((* in BSON, which is used as an intermediate step when
serialising in binary, [`A _] and [`O _] are
indistinguishable. For this reason, we set [bson_relaxation]
when destructing the JSON. *)matchJson.destruct~bson_relaxation:trueError_monad.trace_encodingjsonwith|[]->assertfalse(* see [`A [] | `O []] above *)|trace->Sometrace|exceptionJson.Cannot_destruct_->Some[Unparsable_RPC_errorjson]))json)letget_service=get_service~error:error_encodingletpost_service=post_service~error:error_encodingletdelete_service=delete_service~error:error_encodingletpatch_service=patch_service~error:error_encodingletput_service=put_service~error:error_encodingleterror_service=get_service~description:"Schema for all the RPC errors from the shell"~query:RPC_query.empty~output:Data_encoding.json_schemaRPC_path.(root/"errors")let()=error_path:=Some(forge_requesterror_service()())letdescription_service=description_service~description:"RPCs documentation and input/output schema"error_encodingRPC_path.(root/"describe")