1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021(*****************************************************************************)(* *)(* 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?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?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()=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)?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)