Docs: add rpc documentation generation

This commit is contained in:
Vincent Botbol 2018-03-07 10:44:24 +01:00 committed by Benjamin Canou
parent 385a600e98
commit 55d25c6600
9 changed files with 757 additions and 2 deletions

1
.gitignore vendored
View File

@ -22,6 +22,7 @@ __pycache__
/docs/introduction/readme.rst
/docs/api/errors.rst
/docs/api/rpc.rst
/docs/_extensions/*.pyc
*.install

View File

@ -7,6 +7,7 @@ BUILDDIR = _build
DOCGENDIR = doc_gen
DOCERRORDIR = $(DOCGENDIR)/errors
DOCRPCDIR = $(DOCGENDIR)/rpcs
all: html linkcheck
@ -17,11 +18,15 @@ api/errors.rst: $(DOCERRORDIR)/error_doc.ml
@jbuilder build $(DOCERRORDIR)/error_doc.exe
../_build/default/docs/$(DOCERRORDIR)/error_doc.exe > api/errors.rst
api/rpc.rst: $(DOCRPCDIR)/rpc_doc.ml $(DOCRPCDIR)/usage.rst $(DOCRPCDIR)/run_rpc_doc.sh
@jbuilder build $(DOCRPCDIR)/rpc_doc.exe
./$(DOCRPCDIR)/run_rpc_doc.sh > api/rpc.rst
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
html: Makefile api/errors.rst
html: Makefile api/errors.rst api/rpc.rst
@$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
clean:

View File

@ -70,7 +70,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'usage.rst']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

24
docs/doc_gen/rpcs/jbuild Normal file
View File

@ -0,0 +1,24 @@
(jbuild_version 1)
(executable
((name rpc_doc)
(libraries
(tezos-base
tezos-rpc-http
tezos-client-base
tezos-client-commands
tezos-client-base-unix))
(flags (:standard -w -9+27-30-32-40@8
-safe-string
-open Tezos_base__TzPervasives
-open Tezos_rpc_http
-open Tezos_client_base
-open Tezos_client_commands
-open Tezos_client_base_unix
-linkall))
))
(alias
((name runtest_indent)
(deps ((glob_files *.ml*)))
(action (run bash ${libexec:tezos-stdlib:test-ocp-indent.sh} ${^}))))

View File

@ -0,0 +1,633 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2018. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
(* Utility functions *)
exception Unsupported_construct
type input = {
int : int -> int -> string option -> string list -> int ;
float : string option -> string list -> float ;
string : string option -> string list -> string ;
bool : string option -> string list -> bool ;
continue : string option -> string list -> bool ;
display : string -> unit ;
}
open Json_schema
(* generic JSON generation from a schema with callback for random or
interactive filling *)
let fill_in ?(show_optionals=true) input schema : ([> `A of 'a list | `Null | `O of (string * 'a) list | `String of string ]
as 'a) =
let rec element path { title ; kind }=
match kind with
| Integer { minimum ; maximum } ->
let minimum =
match minimum with
| None -> min_int
| Some (m, `Inclusive) -> int_of_float m
| Some (m, `Exclusive) -> int_of_float m + 1 in
let maximum =
match maximum with
| None -> max_int
| Some (m, `Inclusive) -> int_of_float m
| Some (m, `Exclusive) -> int_of_float m - 1 in
let i = input.int minimum maximum title path in
`Float (float i)
| Number _ ->
let f = input.float title path in
`Float f
| Boolean ->
let f = input.bool title path in
`Bool f
| String _ ->
let f = input.string title path in
`String f
| Combine ((One_of | Any_of), elts) ->
let nb = List.length elts in
let n = input.int 0 (nb - 1) (Some "Select the schema to follow") path in
element path (List.nth elts n)
| Combine ((All_of | Not), _) -> raise Unsupported_construct
| Def_ref name ->
(`String (Json_query.json_pointer_of_path name))
| Id_ref _ | Ext_ref _ ->
raise Unsupported_construct
| Array (elts, _) ->
let rec fill_loop acc n ls =
match ls with
| [] -> acc
| elt :: elts ->
let json = element (string_of_int n :: path) elt in
fill_loop (json :: acc) (succ n) elts
in
let acc = fill_loop [] 0 elts in
(`A (List.rev acc))
| Object { properties } ->
let properties =
if show_optionals
then properties
else (List.filter (fun (_, _, b, _) -> b) properties) in
let rec fill_loop acc ls =
match ls with
| [] -> acc
| (n, elt, _, _) :: elts ->
let json = element (n :: path) elt in
fill_loop ((n, json) :: acc) elts
in
let acc = fill_loop [] properties in
(`O (List.rev acc))
| Monomorphic_array (elt, specs) ->
let rec fill_loop acc min n max =
if n > max then
acc
else
let json = element (string_of_int n :: path) elt in
if n < min || input.continue title path then
fill_loop (json :: acc) min (succ n) max
else (json :: acc)
in
let max = match specs.max_items with None -> max_int | Some m -> m in
let acc = fill_loop [] specs.min_items 0 max in
`A (List.rev acc)
| Any -> raise Unsupported_construct
| Dummy -> raise Unsupported_construct
| Null -> `Null
in
element [] (Json_schema.root schema)
let random_fill_in ?(show_optionals=true) schema =
let display _ = () in
let int min max _ _ =
let max = Int64.of_int max
and min = Int64.of_int min in
let range = Int64.sub max min in
let random_int64 = Int64.add (Random.int64 range) min in
Int64.to_int random_int64 in
let string _title _ = "" in
let float _ _ = Random.float infinity in
let bool _ _ = (Random.int 2 = 0) in
let continue _ _ = (Random.int 4 = 0) in
fill_in ~show_optionals
{ int ; float ; string ; bool ; display ; continue }
schema
type service_repr =
{ path : string list ;
meth : Resto.meth ;
description : string ;
input : Json_schema.schema option;
output : Json_schema.schema ;
example : string option;
error : Json_schema.schema option
}
type service_tree =
| Root of service_tree list
| Node of service_repr * service_tree list
| SymbNode of string list * service_tree list
let make_descr = function
| None | Some "" -> "No description"
| Some s -> s
let repr_of_service path
RPC_description.{ description ; error ;
meth ; input ; output ; _ } : service_repr=
(* TODO? : check that json schema are not empty *)
(* let escape_html_string str =
* let open Stringext in
* let str = replace_all str "<" "&lt;" in
* replace_all str ">" "&gt;"
* in
*
* let example = begin
* match input with
* | None -> None
* | Some input when input = Json_schema.any -> None
* | Some input -> begin
* let json = random_fill_in ~show_optionals:true input in
* (\* curl -X METH -H "Content-type: application/json" http://<address>:<port><path> -d '<schema>' *\)
*
* let tezos_client_cmd_example =
* Format.asprintf "tezos-client rpc call /%s with '%s'"
* (String.concat "/" path |> escape_html_string)
* (Data_encoding.Json.to_string ~minify:true json)
* in
* let curl_cmd_example =
* Format.asprintf "curl -X %s -H \"Content-type: application/json\" http://&lt;address&gt;:&lt;port&gt;/%s -d '%s'"
* (RPC_service.string_of_meth meth)
* (String.concat "/" path |> escape_html_string)
* (Data_encoding.Json.to_string ~minify:true json)
* in
* let open Format in
*
* Some (
* List.fold_left (fun acc s ->
* (Format.sprintf "<div class=\"cmdline\">%s</div>" s) :: acc)
* [] [tezos_client_cmd_example ; curl_cmd_example]
* |> List.rev |> String.concat "or"
* )
*
* end
* end in *)
{ path ; meth ;
description = make_descr description ;
input ; output ;
example=None ; error = Some error }
open Format
let pp_print_service fmt
{ path ; meth }
=
fprintf fmt "%s %s" (Resto.string_of_meth meth) (String.concat "/" path)
let rec pp_print_service_tree fmt = function
| Root l ->
fprintf fmt "@[<v 2>/";
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_service_tree tree
) l;
fprintf fmt "@]"
| Node (repr, l) ->
fprintf fmt "@[<v 2>%a" pp_print_service repr;
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_service_tree tree
) l;
fprintf fmt "@]"
| SymbNode (sl, l) ->
fprintf fmt "@[<v 2>%s" (String.concat "/" sl);
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_service_tree tree
) l;
fprintf fmt "@]"
let collected_args = ref []
let make_tree cctxt path =
(* TODO : discuss about automatic example generation *)
let collect arg =
if not (arg.RPC_arg.descr <> None && List.mem arg !collected_args) then
collected_args := arg :: !collected_args
in
let open RPC_description in
describe cctxt ~recurse:true path >>=? fun dir ->
let rec loop path : _ directory -> service_tree list = function
| Dynamic descr ->
[ Node ({ path ; meth=`POST ;
description=make_descr descr ;
input = None ; output = Json_schema.any ;
example = None ; error = None }, []) ]
| Empty -> []
| Static { services ; subdirs = None } ->
let l = RPC_service.MethMap.bindings services in
let l = List.map snd l in
List.map
(fun service -> Node (repr_of_service path service, []))
l
| Static { services ; subdirs = Some (Suffixes subdirs) } ->
let subdirs = Resto.StringMap.bindings subdirs in
let l = List.map (fun (name, subdir) ->
loop (path @ [ name ]) subdir
) subdirs |> List.concat
in
let services = RPC_service.MethMap.bindings services in
let services = List.map snd services in
begin
match services with
| [] -> [ SymbNode (path, l) ]
| service::[] -> [ Node (repr_of_service path service, l) ]
| _ -> assert false (* ? *)
end
| Static { services ; subdirs = Some (Arg (arg, solo)) } ->
collect arg;
let name = Printf.sprintf "<%s>" arg.RPC_arg.name in
let services = RPC_service.MethMap.bindings services in
let services = List.map snd services in
let l = loop (path @ [ name ]) solo in
begin
match services with
| [] -> [ SymbNode (path, l) ]
| service::[] -> [ Node (repr_of_service path service, l) ]
| _ -> assert false (* ? *)
end
in
return (Root (loop path dir))
let rec pp_print_hierarchy fmt =
let open Format in
function
| Root l ->
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_hierarchy tree
) l;
fprintf fmt "@]"
| SymbNode (path, l)
| Node ( { path } , l) ->
if List.length path = 0 then begin
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_hierarchy tree
) l;
fprintf fmt "@]"
end
else
begin
let name = "/" ^ List.hd (List.rev path) in
let offset = max 2 (String.length name / 2) in
if List.length l = 0 then
pp_open_vbox fmt 0
else
pp_open_vbox fmt offset;
fprintf fmt "%s" name;
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" pp_print_hierarchy tree)
l;
pp_close_box fmt ()
end
(**************** RST PRINTING ****************)
let pp_print_rst_title ~char ppf title =
let sub = String.map (fun _ -> char) title in
Format.fprintf ppf "@[<v 0>%s@ %s@ @]" title sub
let pp_print_rst_h1 = pp_print_rst_title ~char:'#'
let pp_print_rst_h2 = pp_print_rst_title ~char:'*'
let pp_print_rst_h3 = pp_print_rst_title ~char:'='
let pp_print_rst_h4 = pp_print_rst_title ~char:'`'
let pp_print_rst_raw_html fmt str =
(* let ic = open_in file in *)
fprintf fmt "@[<v 2>.. raw:: html@ @ %s@ @ @]" str
let label_table = Hashtbl.create 17
let make_counter () =
let i = ref 1 in
fun () -> incr i; !i
let count = make_counter ()
let rst_label_of_path path =
let label = Printf.sprintf "ref%d" (count ()) in
Hashtbl.add label_table path label;
"<" ^ label ^ "_>"
let ref_of_path path =
Hashtbl.find label_table path
let rec pp_print_rst_hierarchy fmt ~title node =
fprintf fmt "%a@ " pp_print_rst_h2 title;
let rst_name =
String.lowercase_ascii title
|> String.map (function ' ' -> '-' | x -> x)
in
let rst_name =
let rec loop str =
let open Stringext in
if find_from str ~pattern:"--" <> None then
loop (Stringext.replace_all_assoc str [("--","-")])
else
str
in loop rst_name
in
fprintf fmt "%a@." pp_print_rst_raw_html
(sprintf "<style>#%s * { margin-bottom:0px }\
#%s > *:last-child { margin-bottom:15px }\
#%s > h2 { margin-bottom:15px}</style>" rst_name rst_name rst_name);
let rec loop fmt tree =
match tree with
| Root l ->
(* fprintf fmt "@[<v 4>/"; *)
fprintf fmt "@[<v 0>";
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" loop tree
) l;
fprintf fmt "@]"
| Node ( { path }, l) ->
let name = "/" ^ String.concat "/" path in
fprintf fmt "@[<v 4>";
fprintf fmt "`%s %s`_" name (rst_label_of_path path);
fprintf fmt "@ ";
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" loop tree
) l;
fprintf fmt "@]"
| SymbNode (path, l) ->
if List.length path > 0 then begin
let name = "\\/" ^ String.concat "/" path in
fprintf fmt "@[<v 2>%s" name;
(* fprintf fmt "%s" name; *)
fprintf fmt "@ ";
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" loop tree
) l;
fprintf fmt "@]"
end else
List.iter
(fun tree ->
fprintf fmt "@ ";
fprintf fmt "%a" loop tree
) l
in
loop fmt node
let pp_print_html_tab_button fmt ?(default=false) ~shortlabel ~content path =
let target_ref = ref_of_path path in
fprintf fmt "<button class=\"tablinks%s\" onclick=\"showTab(this, '%s', '%s')\">%s</button>@ "
(if default then " defaultOpen" else "")
(target_ref ^ shortlabel)
target_ref
content
let pp_print_html_tab_content fmt ~tag ~shortlabel ~pp_content ~content path =
let target_ref = ref_of_path path in
fprintf fmt "@[<v 2><div id=\"%s\" class=\"%s tabcontent\" style=\"max-height:200px; overflow:auto\" >@ "
(target_ref ^ shortlabel) target_ref;
fprintf fmt "<%s>@ %a</%s>@ " tag pp_content content tag;
fprintf fmt "</div>@]"
let pp_print_html_tab_content_example fmt ~shortlabel ~pp_content ~content path =
let target_ref = ref_of_path path in
fprintf fmt "@[<v 2><div id=\"%s\" class=\"%s tabcontent\" style=\"max-height:200px; overflow:auto\" >@ %a</div>@]"
(target_ref ^ shortlabel) target_ref pp_content content
let pp_print_html_tabs fmt { path ; description ; input ; output ; example ; error } =
fprintf fmt "@[<v 2>.. raw:: html@ @ ";
fprintf fmt "@[<v 2><div class=\"tab\">@ ";
fprintf fmt "%a" (pp_print_html_tab_button ~default:true ~shortlabel:"descr" ~content:"Description") path;
(match input with
| Some _ ->
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"input" ~content:"Input") path;
| None -> ());
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"output" ~content:"Output") path;
(match example with
| Some _ ->
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"example" ~content:"Example") path;
| None -> ());
(match error with
| Some _ ->
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:"error" ~content:"Errors") path;
| None -> ());
fprintf fmt "</div>@]@ ";
fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"p" ~shortlabel:"descr"
~pp_content:pp_print_string ~content:description) path;
(match input with
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"input"
~pp_content:Json_schema.pp ~content:x) path;
| None -> ());
fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"output"
~pp_content:Json_schema.pp ~content:output) path;
(match example with
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content_example ~shortlabel:"example"
~pp_content:pp_print_string ~content:x) path;
| None -> ());
(match error with
| Some x -> fprintf fmt "%a@ " (pp_print_html_tab_content ~tag:"pre" ~shortlabel:"error"
~pp_content:Json_schema.pp ~content:x) path;
| None -> ());
fprintf fmt "@]"
let pp_print_rst_full_service fmt ({ path ; meth } as repr) =
fprintf fmt ".. _%s :@\n@\n**%s %s**@\n@\n"
(ref_of_path path)
(Resto.string_of_meth meth)
("/" ^ String.concat "/" path);
fprintf fmt "%a" pp_print_html_tabs repr
let rec pp_print_rst_service_tree fmt node =
let open Format in
match node with
| Root l -> (pp_print_list ~pp_sep:pp_print_cut pp_print_rst_service_tree) fmt l
| SymbNode (_, l) -> (pp_print_list ~pp_sep:pp_print_cut pp_print_rst_service_tree) fmt l
| Node ( repr , l) ->
(* Generates services details and ref for links *)
fprintf fmt "%a@\n@\n" pp_print_rst_full_service repr;
fprintf fmt "%a" (pp_print_list ~pp_sep:pp_print_newline pp_print_rst_service_tree) l
let style =
"<style>\
.tab {\
overflow: hidden;\
border: 1px solid #ccc;\
background-color: #f1f1f1;\
}\
.tab button {\
background-color: inherit;\
float: left;\
border: none;\
outline: none;\
cursor: pointer;\
padding: 5px 10px;\
}\
.tab button:hover {\
background-color: #ddd;\
}\
.tab button.active {\
background-color: #ccc;\
}\
.tabcontent {\
display: none;\
padding: 6px 12px;\
border: 1px solid #ccc;\
border-top: none;\
margin-bottom: 20px;\
}\
pre {\
font-size: 12px\
}\
.cmdline { font-family: monospace; background: #343131; padding: 2px 8px;\
border-radius:10px; color: white; margin: 5px; }\
.cmdline+.cmddoc { margin: -5px 5px 0 20px; padding: 5px }\
</style>"
let script =
"<script>\
function showTab(elt, tab, ref) {\
var i, tabcontent, tablinks;\
\
tabcontent = document.getElementsByClassName(ref);\
for (i = 0; i < tabcontent.length; i++) {\
tabcontent[i].style.display = 'none';\
}\
\
tablinks = elt.parentNode.children;\
for (i = 0; i < tablinks.length; i++) {\
tablinks[i].className = tablinks[i].className.replace(' active', '');\
}\
\
document.getElementById(tab).style.display = 'block';\
elt.className += ' active';\
}\
\
document.addEventListener('DOMContentLoaded', function(){\
var a = document.getElementsByClassName('defaultOpen');\
for (i = 0; i < a.length; i++) { a[i].click() }\
})\
</script>"
let ppf = Format.std_formatter
let err_ppf = Format.err_formatter
let run ?(rpc_port=18731) () =
(* Client context *)
let rpc_config = { RPC_client.default_config with port=rpc_port } in
let open Client_config in
let {block; _} = default_cli_args in
let (cctxt : #Tezos_client_base.Client_context.full) =
new Client_context_unix.unix_full ~block ~base_dir: "/" ~rpc_config
in
let print_header () =
(* Style : hack *)
fprintf ppf "%a@." pp_print_rst_raw_html style;
(* Script : hack *)
fprintf ppf "%a@." pp_print_rst_raw_html script;
(* Page title *)
fprintf ppf "%a" pp_print_rst_h1 "Tezos RPCs";
(* include/copy usage.rst from input *)
let rec loop () =
let s = read_line () in
fprintf ppf "%s@\n" s;
loop ()
in begin try loop () with End_of_file -> () end
in
(make_tree cctxt [] >>= function
| Ok service_tree ->
(* Print header!! *)
fprintf ppf "@\n";
print_header ();
fprintf ppf "@\n";
(* Shell RPCs tree *)
fprintf ppf "%a@." (pp_print_rst_hierarchy ~title:"Client RPCs - Index") service_tree;
fprintf ppf "%a" pp_print_rst_h2 "Client RPCs - Full description";
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
Lwt.return 0
| Error _ ->
Format.eprintf "[RPC Doc Generation] Client : Couldn't reach node\n";
Lwt.return 1) >>= function
| 0 ->
(* Alpha Protocol RPCs *)
let path_proto_alpha = String.split '/' "/blocks/head/proto" in
begin
make_tree cctxt path_proto_alpha >>= function
| Ok service_tree ->
(* TODO : replace head by <block_id> ? *)
(* Proto alpha RPCs tree *)
fprintf ppf "%a@." (pp_print_rst_hierarchy ~title:"Protocol Alpha RPCs - Index") service_tree;
fprintf ppf "%a" pp_print_rst_h2 "Protocol Alpha RPCs - Full description";
fprintf ppf "%a@." pp_print_rst_service_tree service_tree;
Lwt.return 0
(* TODO : add dynamic parameter description *)
| Error _ ->
Format.fprintf err_ppf "[RPC Doc Generation] Proto alpha : Couldn't reach node\n";
Lwt.return 1
end
| _ -> Lwt.return 1
let () =
Pervasives.exit
(Lwt_main.run
begin try
if Array.length Sys.argv > 1 then
let rpc_port = int_of_string Sys.argv.(1) in
run ~rpc_port ()
else
run ()
with _ ->
run ()
end)

View File

@ -0,0 +1,56 @@
#!/bin/bash
set -e
set -o pipefail
#**************************************************************************#
#* *#
#* Copyright (c) 2014 - 2018. *#
#* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *#
#* *#
#* All rights reserved. No warranty, explicit or implicit, provided. *#
#* *#
#**************************************************************************#
docgen_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && echo "$(pwd -P)")"
rpc_doc="../_build/default/docs/doc_gen/rpcs/rpc_doc.exe"
tezos_sandboxed_node="${1:-$docgen_dir/../../../src/bin_node/tezos-sandboxed-node.sh}"
tezos_init_sandboxed_client="${3:-$docgen_dir/../../../src/bin_client/tezos-init-sandboxed-client.sh}"
local_node="${2:-$docgen_dir/../../../_build/default/src/bin_node/main.exe}"
local_client="${2:-$docgen_dir/../../../_build/default/src/bin_client/main_client.exe}"
sandbox_file="$docgen_dir/sandbox.json"
usage="$docgen_dir/usage.rst"
source $tezos_sandboxed_node
source $tezos_init_sandboxed_client
start_node() {
local id=${1:-1}
start_sandboxed_node $id
init_sandboxed_client $id
wait_for_the_node_to_be_ready
add_sandboxed_bootstrap_identities
client_instances+=("$client")
export "client$id=$client"
}
cleanup() {
set -e
cleanup_nodes
cleanup_clients
}
trap cleanup EXIT INT
# Default to 7 to avoid potentially running nodes
# TODO : get first available port
start_node 7 >&2
activate_alpha >&2
sleep 2
$rpc_doc $rpc < $usage | sed 's|/blocks/head/|/blocks/<block_id>/|g'

View File

@ -0,0 +1,14 @@
{
"genesis_pubkey":
"edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2",
"bootstrap_keys": [
"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav",
"edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9",
"edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV",
"edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU",
"edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n"
],
"slot_durations" : [ 1, 0 ],
"cycle_length" : 128,
"first_free_baking_slot" : 4
}

View File

@ -0,0 +1,21 @@
Usage
*****
In order to interact with a Tezos node, you may use RPC calls through the
client using this command ``tezos-client rpc call <url>``.
For instance, if you wish to request the current balance of a given
block and contract, you can call the associated RPC via the command :
``$ tezos-client rpc call
/blocks/<block_id>/proto/context/contracts/<contract_id>/balance``.
A RPC may takes an *input* and generates an *output* both in JSON
format. For example, the previous RPC call, that does not require an
input, would display on the standard output : ``{ "balance":
"4000000000000" }``. When calling a RPC that requires an input
through command-line, you will be prompted to provide the JSON input
in your default configured text editor.
In the following sections, you may find the complete list of RPCs
available for the client and for the protocol Alpha. You may also find
input, output and errors JSON schema.

View File

@ -84,6 +84,7 @@ license when the main network lunches.
api/api-inline
api/cli-commands
api/errors
api/rpc
Indices and tables
==================