123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2020 Nomadic Labs <contact@nomadic-labs.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. *)(* *)(*****************************************************************************)openProtocol_client_contextopenProtocolopenAlpha_contextopenTezos_michelinetypeerror+=Contract_has_no_scriptofContract_hash.ttypeerror+=Contract_has_no_storageofContract.ttypeerror+=Entrypoint_mismatchofstring*(Script.expr*Script.expr)optiontypeerror+=Action_unwrapping_errorofstring*Script.exprtypeerror+=Not_a_viewable_entrypointofEntrypoint.ttypeerror+=Not_an_entrypointofScript.exprtypeerror+=Not_enough_balanceofZ.t*Z.ttypeerror+=Not_enough_allowanceofZ.t*Z.ttypeerror+=Unsafe_allowance_changeofZ.ttypeerror+=Unexpected_errorofScript.location*Script.exprletentrypoint_mismatch_explanationppf(name,ty)=matchtywith|None->Format.fprintfppf"Entrypoint %s is missing"name|Some(ty,expected)->Format.fprintfppf"Entrypoint \"%s\" has type @[%a@], but should have type @[%a@]"nameMichelson_v1_printer.print_exprtyMichelson_v1_printer.print_exprexpectedlet()=register_error_kind`Permanent~id:"fa12ContractHasNoScript"~title:"The given contract is not a smart contract"~description:"An FA1.2 command has referenced a scriptless contract."~pp:(funppfcontract->Format.fprintfppf"Contract %a is not a smart contract, it has no script."Contract_hash.ppcontract)Data_encoding.(obj1(req"contract"Contract.originated_encoding))(functionContract_has_no_scriptc->Somec|_->None)(func->Contract_has_no_scriptc);register_error_kind`Permanent~id:"fa12ContractHasNoStorage"~title:"The given contract has no storage"~description:"An FA1.2 command made a call on a contract that has no storage."~pp:(funppfcontract->Format.fprintfppf"Contract %a has no storage."Contract.ppcontract)Data_encoding.(obj1(req"contract"Contract.encoding))(functionContract_has_no_storagec->Somec|_->None)(func->Contract_has_no_storagec);register_error_kind`Permanent~id:"entrypointMismatch"~title:"The given contract does not implement the FA1.2 interface"~description:"An FA1.2 command has referenced a smart contract whose script does not \
implement at least one FA1.2 entrypoint, or with an incompatible type. \
See TZIP-7 \
(https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md) \
for documentation on FA1.2."~pp:(funppf(name,ty)->Format.fprintfppf"Not a supported FA1.2 contract.@\n%a."entrypoint_mismatch_explanation(name,ty))Data_encoding.(obj2(req"name"string)(req"type"(option(tup2Script.expr_encodingScript.expr_encoding))))(functionEntrypoint_mismatch(n,t)->Some(n,t)|_->None)(fun(n,t)->Entrypoint_mismatch(n,t));register_error_kind`Permanent~id:"actionUnwrappingError"~title:"The argument is not for an FA1.2 parameter"~description:"The argument's type does not correspond to that of the corresponding \
FA1.2 entrypoint."~pp:(funppf(entrypoint,expr)->Format.fprintfppf"Not a supported FA1.2 entrypoint argument.@\nEntrypoint: %s@\n%a."entrypointMichelson_v1_printer.print_exprexpr)Data_encoding.(obj2(req"entrypoint"string)(req"expr"Script.expr_encoding))(functionAction_unwrapping_error(s,e)->Some(s,e)|_->None)(fun(s,e)->Action_unwrapping_error(s,e));register_error_kind`Permanent~id:"notAViewableEntrypoint"~title:"The entrypoint is not viewable"~description:"A transaction made a call on an entrypoint expecting it to implement \
the 'view' type."~pp:(funppfentrypoint->Format.fprintfppf"Entrypoint %a is not viewable."Entrypoint.ppentrypoint)Data_encoding.(obj1(req"entrypoint"Entrypoint.simple_encoding))(functionNot_a_viewable_entrypointe->Somee|_->None)(fune->Not_a_viewable_entrypointe);register_error_kind`Permanent~id:"notAnEntrypoint"~title:"The expression is not for an entrypoint"~description:"The parameter value of the contract call refers to a non-existing \
entrypoint."~pp:(funppfparam->Format.fprintfppf"Not a parameter for an entrypoint.@\n%a."Michelson_v1_printer.print_exprparam)Data_encoding.(obj1(req"param"Script.expr_encoding))(functionNot_an_entrypointe->Somee|_->None)(fune->Not_an_entrypointe);register_error_kind`Permanent~id:"notEnoughBalance"~title:"The sender does not have enough balance"~description:"An FA1.2 transfer failed because the sender does not have enough \
balance."~pp:(funppf(required,present)->Format.fprintfppf"Not enough balance.@\nRequired: %a.@\nPresent: %a."Z.pp_printrequiredZ.pp_printpresent)Data_encoding.(obj2(req"present"n)(req"required"n))(functionNot_enough_balance(p,r)->Some(p,r)|_->None)(fun(p,r)->Not_enough_balance(p,r));register_error_kind`Permanent~id:"notEnoughAllowance"~title:"The sender does not have enough allowance"~description:"An FA1.2 transfer failed because the receiver does not have enough \
allowance to ask for a transfer from the sender."~pp:(funppf(required,present)->Format.fprintfppf"Not enough allowance.@\nRequired: %a.@\nPresent: %a."Z.pp_printrequiredZ.pp_printpresent)Data_encoding.(obj2(req"present"n)(req"required"n))(functionNot_enough_allowance(p,r)->Some(p,r)|_->None)(fun(p,r)->Not_enough_allowance(p,r));register_error_kind`Permanent~id:"unsafeAllowanceChange"~title:"The allowance change is unsafe"~description:"An FA1.2 non-zero allowance change failed because the current allowance \
is non-zero. For more explanation on why such allowance change is \
unsafe, please look at TZIP-7 \
(https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md#approve)."~pp:(funppfprevious->Format.fprintfppf"Unsafe allowance change@\nPrevious: %a."Z.pp_printprevious)Data_encoding.(obj1(req"previous"n))(functionUnsafe_allowance_changep->Somep|_->None)(funp->Unsafe_allowance_changep);register_error_kind`Permanent~id:"fa12UnexpectedError"~title:"Unexpected error during FA1.2 contract interpretation"~description:"An unexpected Michelson error was reached during the interpretation of \
an FA1.2 contract."~pp:(funppf(loc,expr)->Format.fprintfppf"An unexpected error was reached at location %d with: %a."locMichelson_v1_printer.print_exprexpr)Data_encoding.(obj2(req"location"Script.location_encoding)(req"value"Script.expr_encoding))(functionUnexpected_error(loc,expr)->Some(loc,expr)|_->None)(fun(loc,expr)->Unexpected_error(loc,expr))letcallback_encoding=Data_encoding.(conv(fun(c,e)->(c,Option.value~default:""e))(fun(c,e)->(c,ifString.equale""thenNoneelseSomee))(tup2Contract.encodingVariable.string))(** Michelson combinators *)letpair~locab=Micheline.Prim(loc,Script.D_Pair,[a;b],[])letnat~loci=Micheline.Int(loc,i)letunit~loc=Micheline.Prim(loc,Script.D_Unit,[],[])letbytes~locb=Micheline.Bytes(loc,b)letaddress~locaddr=bytes~loc(Data_encoding.Binary.to_bytes_exnContract.encodingaddr)letcallback~loc?entrypointaddr=bytes~loc(Data_encoding.Binary.to_bytes_exncallback_encoding(addr,entrypoint))(** Types *)(** Michelson type combinators: produce a Michelson node of the
expected type, and a function to check another node is
syntactically equivalent. *)typetype_eq_combinator=Script.node*(Script.node->bool)(** [t_pair ~loc l] takes a list of types and respective equivalence
check functions, and returns a type of n-ary pair of such types and
a function checking syntactical equivalence with another node. *)lett_pair~locl:type_eq_combinator=letvalues,are_ty=List.splitlinletis_pairp=matchpwith|Micheline.Prim(_,Script.T_pair,l,_)->(letres=List.for_all2~when_different_lengths:()(funis_tyv->is_tyv)are_tylinmatchreswithOkb->b|Error()->false)|_->falsein(Micheline.Prim(loc,Script.T_pair,values,[]),is_pair)(** [t_unit ~loc] returns a Micheline node for the `unit` type, and
a function checking another node is syntactically equivalent. *)lett_unit~loc:type_eq_combinator=letis_unitp=matchpwithMicheline.Prim(_,Script.T_unit,[],_)->true|_->falsein(Micheline.Prim(loc,Script.T_unit,[],[]),is_unit)(** [t_nat ~loc] returns a Micheline node for the `nat` type, and
a function checking another node is syntactically equivalent. *)lett_nat~loc:type_eq_combinator=letis_natp=matchpwithMicheline.Prim(_,Script.T_nat,[],_)->true|_->falsein(Micheline.Prim(loc,Script.T_nat,[],[]),is_nat)(** [t_address ~loc] returns a Micheline node for the `address`
type, and a function checking another node is syntactically
equivalent. *)lett_address~loc:type_eq_combinator=letis_addressp=matchpwith|Micheline.Prim(_,Script.T_address,[],_)->true|_->falsein(Micheline.Prim(loc,Script.T_address,[],[]),is_address)(** [t_contract ~loc (c, is_c)] takes a node representing a Michelson
type and its own syntactical equivalence checker, and returns a
Micheline node for the type `contract c`, and a function checking
another node is syntactically equivalent. *)lett_contract~loc(a,is_a):type_eq_combinator=letis_contractc=matchcwith|Micheline.Prim(_,Script.T_contract,[a],_)->is_aa|_->falsein(Micheline.Prim(loc,Script.T_contract,[a],[]),is_contract)(** [t_view ~loc a b] takes two node [a] and [b] and their syntactical
equivalence checking functions, and returns a Micheline node for
the `view a b` type, and a function checking another node is
syntactically equivalent. The view type is defined by
[TZIP4](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-4/tzip-4.md).
*)lett_view~locab:type_eq_combinator=t_pair~loc[a;t_contract~locb](** * Actions *)(** Corresponds to
[TZIP7](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md)
entrypoints. *)(** A callback from a view can be on a specific entrypoint of the
contract, or the default one if not specified. *)typecallback_contract=Contract.t*stringoptiontypeaction=|TransferofContract.t*Contract.t*Z.t|ApproveofContract.t*Z.t|Get_allowanceofContract.t*Contract.t*callback_contract|Get_balanceofContract.t*callback_contract|Get_total_supplyofcallback_contractletprint_callback_contractppf(c,etp)=Format.fprintfppf"%a%s"Contract.ppc(matchetpwithNone|Some""->""|Someetp->"%"^etp)letprint_actionppf=function|Transfer(src,dst,amount)->Format.fprintfppf"Transfer (%a, %a, %a)"Contract.ppsrcContract.ppdstZ.pp_printamount|Approve(addr,amount)->Format.fprintfppf"Approve (%a, %a)"Contract.ppaddrZ.pp_printamount|Get_allowance(src,dst,callback)->Format.fprintfppf"Get_allowance (%a, %a, %a)"Contract.ppsrcContract.ppdstprint_callback_contractcallback|Get_balance(addr,callback)->Format.fprintfppf"Get_balance (%a, %a)"Contract.ppaddrprint_callback_contractcallback|Get_total_supplycallback->Format.fprintfppf"Get_total_supply (%a)"print_callback_contractcallbacklettransfer_encoding=Data_encoding.(case~title:"transfer"(Tag0)(obj3(req"transfer_source"Contract.encoding)(req"transfer_destination"Contract.encoding)(req"transfer_amount"n))(function|Transfer(src,dst,amount)->Some(src,dst,amount)|_->None)(fun(src,dst,amount)->Transfer(src,dst,amount)))letapprove_encoding=Data_encoding.(case~title:"approve"(Tag1)(obj2(req"approve_address"Contract.encoding)(req"approve_amount"n))(functionApprove(addr,amount)->Some(addr,amount)|_->None)(fun(addr,amount)->Approve(addr,amount)))letgetBalance_encoding=Data_encoding.(case~title:"getBalance"(Tag2)(obj2(req"getBalance_address"Contract.encoding)(req"getBalance_callback"callback_encoding))(function|Get_balance(addr,callback)->Some(addr,callback)|_->None)(fun(addr,callback)->Get_balance(addr,callback)))letgetAllowance_encoding=Data_encoding.(case~title:"getAllowance"(Tag3)(obj3(req"getAllowance_source"Contract.encoding)(req"getAllowance_destination"Contract.encoding)(req"getAllowance_callback"callback_encoding))(function|Get_allowance(src,dst,callback)->Some(src,dst,callback)|_->None)(fun(src,dst,callback)->Get_allowance(src,dst,callback)))letgetTotalSupply_encoding=Data_encoding.(case~title:"getTotalSupply"(Tag4)(obj1(req"getTotalSupply_callback"callback_encoding))(functionGet_total_supplycallback->Somecallback|_->None)(funcallback->Get_total_supplycallback))letaction_encoding=Data_encoding.union[transfer_encoding;approve_encoding;getBalance_encoding;getAllowance_encoding;getTotalSupply_encoding;]lettransfer_type~loc=t_pair~loc[t_address~loc;t_address~loc;t_nat~loc]letapprove_type~loc=t_pair~loc[t_address~loc;t_nat~loc]letgetAllowance_type~loc=t_view~loc(t_pair~loc[t_address~loc;t_address~loc])(t_nat~loc)letgetBalance_type~loc=t_view~loc(t_address~loc)(t_nat~loc)letgetTotalSupply_type~loc=t_view~loc(t_unit~loc)(t_nat~loc)letstandard_entrypoints=letloc=-1in[("transfer",transfer_type~loc);("approve",approve_type~loc);("getAllowance",getAllowance_type~loc);("getBalance",getBalance_type~loc);("getTotalSupply",getTotalSupply_type~loc);]letview_input~locaction=matchactionwith|Get_allowance(source,destination,_)->pair~loc(address~locsource)(address~locdestination)|Get_balance(addr,_)->address~locaddr|Get_total_supply_->unit~loc|_->unit~locletaction_to_expr~locaction=matchactionwith|Transfer(source,destination,amount)->pair~loc(address~locsource)(pair~loc(address~locdestination)(nat~locamount))|Approve(addr,amount)->pair~loc(address~locaddr)(nat~locamount)|Get_allowance(_,_,(cb,entrypoint))->letinput=view_input~locactioninpair~locinput(callback~loc?entrypointcb)|Get_balance(_,(cb,entrypoint))->letinput=view_input~locactioninpair~locinput(callback~loc?entrypointcb)|Get_total_supply(cb,entrypoint)->letinput=view_input~locactioninpair~locinput(callback~loc?entrypointcb)letparse_addresserror=letopenResult_syntaxinfunction|Micheline.Bytes(_,b)->return@@Data_encoding.Binary.of_bytes_exnContract.encodingb|String(_,s)->(matchContract.of_b58checkswithOkc->returnc|Error_->error())|_->error()letparse_callbackerrorexpr=letof_b58_check(c,entrypoint)=matchContract.of_b58checkcwith|Okc->Ok(c,entrypoint)|Error_->error()inmatchexprwith|Micheline.Bytes(_,b)->(matchData_encoding.Binary.of_bytescallback_encodingbwith|Ok(c,entrypoint)->Ok(c,entrypoint)|Error_->error())|String(_,s)->(matchString.index_opts'%'with|None->of_b58_check(s,None)|Somepos->(letlen=String.lengths-pos-1inletname=String.subs(pos+1)leninmatch(String.subs0pos,name)with|addr,"default"->of_b58_check(addr,None)|addr,name->of_b58_check(addr,Somename)))|_->error()letaction_of_expr~entrypointexpr=letopenResult_syntaxinletopenMichelineinleterror()=tzfail(Action_unwrapping_error(entrypoint,Micheline.strip_locationsexpr))inmatch(entrypoint,expr)with(* Transfer operation before comb pairs. *)|("transfer",Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))assource);Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))asdestination);Int(_,amount);],_);],_))(* Transfer operation since Edo comb pairs are now directly interpreted as a
tuple of 3 elements instead of a pair inside a pair. *)|("transfer",Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))assource);((Bytes(_,_)|String(_,_))asdestination);Int(_,amount);],_))->let*source=parse_addresserrorsourceinlet*destination=parse_addresserrordestinationinreturn(Transfer(source,destination,amount))|("approve",Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))asaddr);Int(_,amount)],_))->let*addr=parse_addresserroraddrinreturn(Approve(addr,amount))|("getBalance",Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))asaddr);((Bytes(_,_)|String(_,_))ascb);],_))->let*addr=parse_addresserroraddrinlet*callback=parse_callbackerrorcbinreturn(Get_balance(addr,callback))|("getAllowance",Prim(_,Script.D_Pair,[Prim(_,Script.D_Pair,[((Bytes(_,_)|String(_,_))assource);((Bytes(_,_)|String(_,_))asdestination);],_);((Bytes(_,_)|String(_,_))ascontract);],_))->let*source=parse_addresserrorsourceinlet*destination=parse_addresserrordestinationinlet*callback=parse_callbackerrorcontractinreturn(Get_allowance(source,destination,callback))|("getTotalSupply",Prim(_,Script.D_Pair,[Prim(_,Script.D_Unit,[],_);((Bytes(_,_)|String(_,_))ascontract);],_))->let*callback=parse_callbackerrorcontractinreturn(Get_total_supplycallback)|_->error()letfind_entrypoint_in_annoterrorannotsexpr=matchList.find_opt(funannot->annot.[0]='%')annotswith|Someentrypoint->action_of_expr~entrypoint:(String.subentrypoint1(String.lengthentrypoint-1))expr|None->error()letderive_actionexprt_param=leterror()=Result_syntax.tzfail(Not_an_entrypoint(Micheline.strip_locationsexpr))inletrecderiveexprt_param=match(expr,t_param)with|(Micheline.Prim(_,Script.D_Left,[left],_),Micheline.Prim(_,Script.T_or,[t_left;_],_))->deriveleftt_left|(Micheline.Prim(_,Script.D_Right,[right],_),Micheline.Prim(_,Script.T_or,[_;t_right],_))->deriverightt_right|_,Micheline.Prim(_,_,_,annots)->find_entrypoint_in_annoterrorannotsexpr|_->error()inderiveexprt_paramletextract_parametercontract=letopenResult_syntaxinfunction|Micheline.Seq(_,l)->(List.filter_map(function|Micheline.Prim(_,Script.K_parameter,[param],_)->Someparam|_->None)l|>function|param::_->returnparam|_->tzfail(Contract_has_no_scriptcontract))|_->tzfail(Contract_has_no_scriptcontract)letget_contract_parametercctxt~chain~blockcontract=letopenLwt_result_syntaxinlet*script_opt=Client_proto_context.get_scriptcctxt~chain~blockcontract~unparsing_mode:Optimized~normalize_types:trueinmatchscript_optwith|None->tzfail(Contract_has_no_scriptcontract)|Some{code;_}->(matchScript_repr.force_decodecodewith|Error_->tzfail(Contract_has_no_scriptcontract)|Okcode->Lwt.return(extract_parametercontract(Micheline.rootcode)))letconvert_wrapped_parameter_into_actioncctxt~chain~blockcontractparam=letopenLwt_result_syntaxinlet*parameter=get_contract_parametercctxt~chain~blockcontractinLwt.return(derive_actionparamparameter)letcheck_entrypointentrypoints(name,(expected_ty,check))=letopenResult_syntaxinmatchList.assoc_opt~equal:String.equalnameentrypointswith|None->tzfail(Entrypoint_mismatch(name,None))|Somety->ifnot(check(Micheline.rootty))thentzfail(Entrypoint_mismatch(name,Some(ty,Micheline.strip_locationsexpected_ty)))elsereturn_unitletaction_to_entrypoint=lettransfer=Entrypoint.of_string_strict_exn"transfer"inletapprove=Entrypoint.of_string_strict_exn"approve"inletget_allowance=Entrypoint.of_string_strict_exn"getAllowance"inletget_balance=Entrypoint.of_string_strict_exn"getBalance"inletget_total_supply=Entrypoint.of_string_strict_exn"getTotalSupply"infunction|Transfer(_,_,_)->transfer|Approve(_,_)->approve|Get_allowance(_,_,_)->get_allowance|Get_balance(_,_)->get_balance|Get_total_supply_->get_total_supplyletcontract_has_fa12_interface:#Protocol_client_context.rpc_context->chain:Shell_services.chain->block:Shell_services.block->contract:Contract_hash.t->unit->unittzresultLwt.t=letopenLwt_result_syntaxinfuncctxt~chain~block~contract()->let*entrypoints=Michelson_v1_entrypoints.list_contract_entrypointscctxt~chain~block~contract~normalize_types:trueinlet*?()=List.iter_e(check_entrypointentrypoints)standard_entrypointsinreturn_unitlettranslate_action_to_argumentaction=letentrypoint=action_to_entrypointactioninletexpr=Micheline.strip_locations(action_to_expr~loc:()action)|>Script.lazy_exprin(entrypoint,expr)letparse_error=letopenMichelineinfunction|("NotEnoughBalance",Prim(_,Script.D_Pair,[Int(_,required);Int(_,present)],_))->Some(Not_enough_balance(required,present))|("NotEnoughAllowance",Prim(_,Script.D_Pair,[Int(_,required);Int(_,present)],_))->Some(Not_enough_allowance(required,present))|"UnsafeAllowanceChange",Int(_,previous)->Some(Unsafe_allowance_changeprevious)|_->Noneletextract_errortrace=letopenMichelineinTzTrace.fold(fun_error->matcherrorwith|Environment.Ecoproto_error(Script_interpreter.Reject(loc,param,_))->(matchrootparamwith|Prim(_,Script.D_Pair,[String(_,error);res],_)->parse_error(error,res)|_->Some(Unexpected_error(loc,param)))|_->None)Nonetraceletcall_contract(cctxt:#Protocol_client_context.full)~chain~block?confirmations?dry_run?verbose_signing?branch~source~src_pk~src_sk~contract~action~tez_amount?fee?gas_limit?safety_guard?storage_limit?counter~fee_parameter()=letopenLwt_result_syntaxinlet*()=contract_has_fa12_interfacecctxt~chain~block~contract()inletentrypoint,parameters=translate_action_to_argumentactioninlet*!result=Client_proto_context.transfer_with_scriptcctxt~chain~block?confirmations?dry_run?branch~source~src_pk~src_sk~destination:(Originatedcontract)~parameters~amount:tez_amount~entrypoint?fee?gas_limit?safety_guard?storage_limit?counter~fee_parameter?verbose_signing()inmatchresultwith|Okres->returnres|Errortrace->(matchextract_errortracewith|None->Lwt.return(Errortrace)|Someerror->tzfailerror)typetoken_transfer={token_contract:string;destination:string;amount:Z.t;tez_amount:stringoption;fee:stringoption;gas_limit:Gas.Arith.integraloption;storage_limit:Z.toption;}lettoken_transfer_encoding=letopenData_encodinginconv(fun{token_contract;destination;amount;tez_amount;fee;gas_limit;storage_limit;}->(token_contract,destination,amount,tez_amount,fee,gas_limit,storage_limit))(fun(token_contract,destination,amount,tez_amount,fee,gas_limit,storage_limit)->{token_contract;destination;amount;tez_amount;fee;gas_limit;storage_limit;})(obj7(req"token_contract"string)(req"destination"string)(req"amount"z)(opt"tez-amount"string)(opt"fee"string)(opt"gas-limit"Gas.Arith.n_integral_encoding)(opt"storage-limit"z))lettez_of_string_exnindexfields=matchTez.of_stringswith|Somet->Okt|None->error_with"Invalid %s notation at entry %i, field \"%s\": %s"Operation_result.tez_symindexfieldslettez_of_opt_string_exnindexfields=Option.map_e(tez_of_string_exnindexfield)sletbuild_transaction_operation?(tez_amount=Tez.zero)?fee?gas_limit?storage_limittokenaction=letentrypoint=action_to_entrypointactioninletparameters=Script.lazy_expr(Micheline.strip_locations(action_to_expr~loc:()action))inletoperation=Transaction{amount=tez_amount;parameters;destination=token;entrypoint}inInjection.prepare_manager_operation~fee:(Limit.of_optionfee)~gas_limit:(Limit.of_optiongas_limit)~storage_limit:(Limit.of_optionstorage_limit)operationletprepare_single_token_transfercctxt?default_fee?default_gas_limit?default_storage_limit~chain~blocksrcindextransfer=letopenLwt_result_syntaxinlet*token=Client_proto_contracts.Originated_contract_alias.find_destinationcctxttransfer.token_contractinlet*()=contract_has_fa12_interfacecctxt~chain~block~contract:token()inlet*dest=Client_proto_contracts.Contract_alias.find_destinationcctxttransfer.destinationinlet*?tez_amount=tez_of_opt_string_exnindex"tez_amount"transfer.tez_amountinlet*?transfer_fee=tez_of_opt_string_exnindex"fee"transfer.feeinletfee=Option.eithertransfer_feedefault_feeinletgas_limit=Option.eithertransfer.gas_limitdefault_gas_limitinletstorage_limit=Option.eithertransfer.storage_limitdefault_storage_limitinletaction=Transfer(src,dest,transfer.amount)inletoperation=build_transaction_operation?tez_amount?fee?gas_limit?storage_limit(Originatedtoken)actioninreturn(Annotated_manager_operation.Annotated_manager_operationoperation)letinject_token_transfer_batch(cctxt:#Protocol_client_context.full)~chain~block?confirmations?dry_run?verbose_signing~sender~source~src_pk~src_sk~token_transfers~fee_parameter?counter?default_fee?default_gas_limit?default_storage_limit?safety_guard()=letopenLwt_result_syntaxinlet*contents=List.mapi_ep(prepare_single_token_transfercctxt?default_fee?default_gas_limit?default_storage_limit~chain~blocksender)token_transfersinlet(Manager_listcontents)=Annotated_manager_operation.manager_of_listcontentsinlet*!result=Injection.inject_manager_operationcctxt~chain~block?confirmations?dry_run?verbose_signing~source~fee:(Limit.of_optiondefault_fee)~gas_limit:(Limit.of_optiondefault_gas_limit)~storage_limit:(Limit.of_optiondefault_storage_limit)?safety_guard?counter~src_pk~src_sk~fee_parametercontentsinmatchresultwith|Ok_->return_unit|Errortrace->(matchextract_errortracewith|None->Lwt.return(Errortrace)|Someerror->tzfailerror)letis_viewable_actionaction=letopenLwt_result_syntaxinmatchactionwith|Get_balance(_,_)|Get_allowance(_,_,_)|Get_total_supply_->return_unit|_->tzfail(Not_a_viewable_entrypoint(action_to_entrypointaction))letrun_view_action(cctxt:#Protocol_client_context.full)~chain~block~sender~contract~action~payer~gas~unparsing_mode()=letopenLwt_result_syntaxinlet*()=is_viewable_actionactioninlet*()=contract_has_fa12_interfacecctxt~chain~block~contract()inletentrypoint=action_to_entrypointactioninletinput=Micheline.strip_locations(view_input~loc:()action)inlet*chain_id=Chain_services.chain_idcctxt~chain()inPlugin.RPC.Scripts.run_tzip4_viewcctxt(chain,block)~contract~input~chain_id~sender~payer~gas~entrypoint~unparsing_mode~now:None~level:None~other_contracts:None~extra_big_maps:Nonelet()=Data_encoding.(Registration.register@@def(Protocol.name^".fa1.2.token_transfer")token_transfer_encoding)