diff --git a/CHANGES.rst b/CHANGES.rst index 9674eaefe0f7f5a7d336f0a8ccae864b919ae6fd..6e8324389b6d7e9708ad0190d1d925fe1dd2a285 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -46,6 +46,9 @@ Node Client ------ +- Added command to get contract's balance of ticket with specified ticketer, content type, and content: + ``octez-client get ticket balance for with ticketer '' and type and content ``. (MR :gl:`!6491`) + Baker ----- diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index fcdcb7aaba9fef3257b586e73adffacb056d18ed..71713c02299129ee6a2a28421b4870e584e28da0 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -85,6 +85,10 @@ let get_script_hash (rpc : #rpc_context) ~chain ~block contract = ok hash) script_opt +let get_contract_ticket_balance (rpc : #rpc_context) ~chain ~block contract key + = + Plugin.RPC.Contract.ticket_balance rpc (chain, block) contract key + let get_frozen_deposits_limit (rpc : #rpc_context) ~chain ~block delegate = Alpha_services.Delegate.frozen_deposits_limit rpc (chain, block) delegate diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index cf0a45469f8359fc76a94248a54a34a56a1816d2..e25b0a0aa97a584207e42524a9eb1a89fd7648af 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -126,6 +126,15 @@ val get_balance : Contract.t -> Tez.t tzresult Lwt.t +(** Calls {!Tezos_protocol_alpha.Protocol.Ticket_services.ticket_balance}. *) +val get_contract_ticket_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Ticket_token.unparsed_token -> + Z.t tzresult Lwt.t + (** Calls {!Tezos_protocol_alpha.Protocol.Delegate_services.frozen_deposits_limit}. *) val get_frozen_deposits_limit : #Protocol_client_context.rpc_context -> diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index 56eed796ce9f183ef236e7f6bedf85a27a979572..faf6eab6d320d8f907ae86027347dfdb2a446224 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -515,6 +515,46 @@ let commands_ro () = (match mn with None -> "unknown" | Some n -> "known as " ^ n) in return_unit); + command + ~group + ~desc: + "Get contract's balance of ticket with specified ticketer, content \ + type, and content." + no_options + (prefixes ["get"; "ticket"; "balance"; "for"] + @@ ContractAlias.destination_param ~name:"src" ~desc:"Source contract." + @@ prefixes ["with"; "ticketer"] + @@ ContractAlias.destination_param + ~name:"ticketer" + ~desc:"Ticketer contract of the ticket." + @@ prefixes ["and"; "type"] + @@ Tezos_clic.param + ~name:"ticket content type" + ~desc:"Type of the content of the ticket." + data_parameter + @@ prefixes ["and"; "content"] + @@ Tezos_clic.param + ~name:"ticket content" + ~desc:"Content of the ticket." + data_parameter + @@ stop) + (fun () contract ticketer content_type content cctxt -> + let open Lwt_result_syntax in + let* balance = + get_contract_ticket_balance + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + Ticket_token. + { + ticketer; + contents_type = content_type.expanded; + contents = content.expanded; + } + in + let*! () = cctxt#answer "%a" Z.pp_print balance in + return_unit); command ~desc:"Get receipt for past operation" (args1 diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 313296f8f42139fae362b949f59e4b8099db5609..aed3c3a7f053869612be4f4f7272ed56d37ad3ed 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -973,6 +973,32 @@ let get_balance_for ?endpoint ~account client = in return @@ Tez.parse_floating output +let spawn_ticket_balance ?hooks ~contract ~ticketer ~content_type ~content + client = + spawn_command + ?hooks + client + [ + "get"; + "ticket"; + "balance"; + "for"; + contract; + "with"; + "ticketer"; + ticketer; + "and"; + "type"; + content_type; + "and"; + "content"; + content; + ] + +let ticket_balance ?hooks ~contract ~ticketer ~content_type ~content client = + spawn_ticket_balance ?hooks ~contract ~ticketer ~content_type ~content client + |> Process.check_and_read_stdout + let spawn_create_mockup ?(sync_mode = Synchronous) ?parameter_file ?bootstrap_accounts_file ~protocol client = let cmd = diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index c1cdb3a872312921cae9591737aad3e1ba418180..ae16f99f73ec65670d735be3ee2aaf6003df966f 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -757,6 +757,26 @@ val get_balance_for : ?endpoint:endpoint -> account:string -> t -> Tez.t Lwt.t val spawn_get_balance_for : ?endpoint:endpoint -> account:string -> t -> Process.t +(** Run [octez-client get ticket balance for contract with ticketer and type and content ]. *) +val ticket_balance : + ?hooks:Process.hooks -> + contract:string -> + ticketer:string -> + content_type:string -> + content:string -> + t -> + string Lwt.t + +(** Same as [ticket_balance], but do not wait for the process to exit. *) +val spawn_ticket_balance : + ?hooks:Process.hooks -> + contract:string -> + ticketer:string -> + content_type:string -> + content:string -> + t -> + Process.t + (** Run [octez-client create mockup]. *) val create_mockup : ?sync_mode:mockup_sync_mode -> @@ -1207,8 +1227,8 @@ val spawn_run_tzip4_view : t -> Process.t -(** Run [tezos-client run tzip4 view .. on contract .. with input .. ] - +(** Run [tezos-client run tzip4 view .. on contract .. with input .. ] + Returns the value returned by a view as a string. Fails if the view or the contract does not exist. If [input] is [None], diff --git a/tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out index 9891a1ba0246478f10172ef64a1e0c24b84816cc..25ecb11eb5424bad47fbcc5ed2ea1da107cd2212 100644 --- a/tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out +++ b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Alpha- Ticket updates in receipt.out @@ -90,3 +90,18 @@ This sequence of operations was run: Account updates: [CONTRACT_HASH] ... +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"red"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"green"' +2 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +0 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +1 diff --git a/tezt/tests/ticket_receipt_and_rpc.ml b/tezt/tests/ticket_receipt_and_rpc.ml index 492acdf189977d510412bd02a0fb5443e0f273d5..1ab2bd7efc5d9477764672fbd006d49774eb8875 100644 --- a/tezt/tests/ticket_receipt_and_rpc.ml +++ b/tezt/tests/ticket_receipt_and_rpc.ml @@ -27,12 +27,12 @@ ------- Component: Michelson Invocation: dune exec tezt/tests/main.exe -- --file ticket_receipt_and_rpc.ml - Subject: Regression tests for ticket receipt and ticket RPC + Subject: Regression tests for ticket receipt/RPC/CLI *) let hooks = Tezos_regression.hooks -let check_ticket_balance client ~contract ~ticketer ~content_type ~content +let rpc_check_ticket_balance client ~contract ~ticketer ~content_type ~content ~expected = let post_body = Ezjsonm.value_from_string @@ -56,6 +56,24 @@ let check_ticket_balance client ~contract ~ticketer ~content_type ~content ~__LOC__ ~error_msg:"expected ticket amount %R, got %L") +let cli_check_ticket_balance client ~hooks ~contract ~ticketer ~content_type + ~content ~expected = + let* actual = + Client.ticket_balance + client + ~hooks + ~contract + ~ticketer + ~content_type + ~content:(sf {|"%s"|} content) + in + return + @@ Check.( + (String.trim actual = string_of_int expected) + string + ~__LOC__ + ~error_msg:"expected ticket amount %R, got %L") + (* Checks how the ticket updates in receipt look like in various cases, such as: - Contract stores multiple tickets of different types. - Contract stores multiple tickets of the same type. @@ -124,52 +142,35 @@ let test_ticket_receipt_and_rpc = ~hooks client in - (* Check that the ticket balance are expected via [ticket_balance] RPC. *) - let* () = - check_ticket_balance - client - ~contract:kt_a - ~ticketer:kt_a - ~content_type:"string" - ~content:"red" - ~expected:1 - in - let* () = - check_ticket_balance - client - ~contract:kt_a - ~ticketer:kt_a - ~content_type:"string" - ~content:"green" - ~expected:2 - in - let* () = - check_ticket_balance - client - ~contract:kt_a - ~ticketer:kt_a - ~content_type:"string" - ~content:"blue" - ~expected:0 - in - let* () = - check_ticket_balance - client - ~contract:kt_b - ~ticketer:kt_a - ~content_type:"string" - ~content:"blue" - ~expected:1 - in - let* () = - check_ticket_balance - client - ~contract:kt_c - ~ticketer:kt_a - ~content_type:"string" - ~content:"blue" - ~expected:1 - in - unit + (* Check that the ticket balance are expected via both RPC and CLI. *) + [ + (kt_a, kt_a, "string", "red", 1); + (kt_a, kt_a, "string", "green", 2); + (kt_a, kt_a, "string", "blue", 0); + (kt_b, kt_a, "string", "blue", 1); + (kt_c, kt_a, "string", "blue", 1); + ] + |> Lwt_list.iter_s + @@ fun (contract, ticketer, content_type, content, expected) -> + let* () = + rpc_check_ticket_balance + client + ~contract + ~ticketer + ~content_type + ~content + ~expected + in + let* () = + cli_check_ticket_balance + client + ~hooks + ~contract + ~ticketer + ~content_type + ~content + ~expected + in + unit let register ~protocols = test_ticket_receipt_and_rpc protocols