Change return type of contract_call/N
This commit is contained in:
@@ -736,14 +736,16 @@ read_aci(Path) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) -> CallTX
|
-spec contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) -> Result
|
||||||
when CallerID :: binary(),
|
when CallerID :: binary(),
|
||||||
Nonce :: pos_integer(),
|
Nonce :: pos_integer(),
|
||||||
AACI :: map(),
|
AACI :: map(),
|
||||||
ConID :: binary(),
|
ConID :: binary(),
|
||||||
Fun :: string(),
|
Fun :: string(),
|
||||||
Args :: [string()],
|
Args :: [string()],
|
||||||
CallTX :: binary().
|
Result :: {ok, CallTX} | {error, Reason},
|
||||||
|
CallTX :: binary(),
|
||||||
|
Reason :: term().
|
||||||
%% @doc
|
%% @doc
|
||||||
%% Form a contract call using hardcoded default values for `Gas', `GasPrice', `Fee',
|
%% Form a contract call using hardcoded default values for `Gas', `GasPrice', `Fee',
|
||||||
%% and `Amount' to simplify the call (10 args is a bit much for normal calls!).
|
%% and `Amount' to simplify the call (10 args is a bit much for normal calls!).
|
||||||
@@ -753,19 +755,19 @@ read_aci(Path) ->
|
|||||||
%% For details on the meaning of these and other argument values see the doc comment
|
%% For details on the meaning of these and other argument values see the doc comment
|
||||||
%% for contract_call/10.
|
%% for contract_call/10.
|
||||||
|
|
||||||
contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) ->
|
contract_call(CallerID, Nonce, AACI, ConID, Fun, Args) ->
|
||||||
Gas = 20000,
|
Gas = 20000,
|
||||||
GasPrice = min_gas_price(),
|
GasPrice = min_gas_price(),
|
||||||
Fee = 200000000000000,
|
Fee = 200000000000000,
|
||||||
Amount = 0,
|
Amount = 0,
|
||||||
contract_call(CallerID, Nonce,
|
contract_call(CallerID, Nonce,
|
||||||
Gas, GasPrice, Fee, Amount,
|
Gas, GasPrice, Fee, Amount,
|
||||||
ACI, ConID, Fun, Args).
|
AACI, ConID, Fun, Args).
|
||||||
|
|
||||||
|
|
||||||
-spec contract_call(CallerID, Nonce,
|
-spec contract_call(CallerID, Nonce,
|
||||||
Gas, GasPrice, Fee, Amount,
|
Gas, GasPrice, Fee, Amount,
|
||||||
AACI, ConID, Fun, Args) -> CallTX
|
AACI, ConID, Fun, Args) -> Result
|
||||||
when CallerID :: binary(),
|
when CallerID :: binary(),
|
||||||
Nonce :: pos_integer(),
|
Nonce :: pos_integer(),
|
||||||
Gas :: pos_integer(),
|
Gas :: pos_integer(),
|
||||||
@@ -776,7 +778,9 @@ contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) ->
|
|||||||
ConID :: binary(),
|
ConID :: binary(),
|
||||||
Fun :: string(),
|
Fun :: string(),
|
||||||
Args :: [string()],
|
Args :: [string()],
|
||||||
CallTX :: binary().
|
Result :: {ok, CallTX} | {error, Reason},
|
||||||
|
CallTX :: binary(),
|
||||||
|
Reason :: term().
|
||||||
%% @doc
|
%% @doc
|
||||||
%% Form a contract call using the supplied values.
|
%% Form a contract call using the supplied values.
|
||||||
%%
|
%%
|
||||||
@@ -885,14 +889,33 @@ contract_call(CallerID, Nonce, ACI, ConID, Fun, Args) ->
|
|||||||
%% if you do not already have a copy, and can check the spec of a function before
|
%% if you do not already have a copy, and can check the spec of a function before
|
||||||
%% trying to form a contract call.
|
%% trying to form a contract call.
|
||||||
|
|
||||||
contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args) ->
|
contract_call(CallerID, Nonce, Gas, GP, Fee, Amount, AACI, ConID, Fun, Args) ->
|
||||||
{ok, CallData} = encode_call_data(ACI, Fun, Args),
|
case encode_call_data(AACI, Fun, Args) of
|
||||||
|
{ok, CD} -> contract_call2(CallerID, Nonce, Gas, GP, Fee, Amount, ConID, CD);
|
||||||
|
Error -> Error
|
||||||
|
end.
|
||||||
|
|
||||||
|
contract_call2(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData) ->
|
||||||
|
try
|
||||||
|
{account_pubkey, PK} = aeser_api_encoder:decode(CallerID),
|
||||||
|
contract_call3(PK, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData)
|
||||||
|
catch
|
||||||
|
Error:Reason -> {Error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
|
contract_call3(PK, Nonce, Gas, GasPrice, Fee, Amount, ConID, CallData) ->
|
||||||
|
try
|
||||||
|
{contract_pubkey, CK} = aeser_api_encoder:decode(ConID),
|
||||||
|
contract_call4(PK, Nonce, Gas, GasPrice, Fee, Amount, CK, CallData)
|
||||||
|
catch
|
||||||
|
Error:Reason -> {Error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
|
contract_call4(PK, Nonce, Gas, GasPrice, Fee, Amount, CK, CallData) ->
|
||||||
ABI = 3,
|
ABI = 3,
|
||||||
TTL = 0,
|
TTL = 0,
|
||||||
CallVersion = 1,
|
CallVersion = 1,
|
||||||
Type = contract_call_tx,
|
Type = contract_call_tx,
|
||||||
{account_pubkey, PK} = aeser_api_encoder:decode(CallerID),
|
|
||||||
{contract_pubkey, CK} = aeser_api_encoder:decode(ConID),
|
|
||||||
Fields =
|
Fields =
|
||||||
[{caller_id, {id, account, PK}},
|
[{caller_id, {id, account, PK}},
|
||||||
{nonce, Nonce},
|
{nonce, Nonce},
|
||||||
@@ -916,7 +939,11 @@ contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args
|
|||||||
{gas_price, int},
|
{gas_price, int},
|
||||||
{call_data, binary}],
|
{call_data, binary}],
|
||||||
TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields),
|
TXB = aeser_chain_objects:serialize(Type, CallVersion, Template, Fields),
|
||||||
aeser_api_encoder:encode(transaction, TXB).
|
try
|
||||||
|
{ok, aeser_api_encoder:encode(transaction, TXB)}
|
||||||
|
catch
|
||||||
|
error:Reason -> {error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
-spec prepare_contract(File) -> {ok, AACI} | {error, Reason}
|
-spec prepare_contract(File) -> {ok, AACI} | {error, Reason}
|
||||||
@@ -929,7 +956,7 @@ contract_call(CallerID, Nonce, Gas, GasPrice, Fee, Amount, ACI, ConID, Fun, Args
|
|||||||
|
|
||||||
prepare_contract(File) ->
|
prepare_contract(File) ->
|
||||||
case aeso_compiler:file(File, [{aci, json}]) of
|
case aeso_compiler:file(File, [{aci, json}]) of
|
||||||
{ok, #{aci := ACI}} -> prepare_aaci(ACI);
|
{ok, #{aci := ACI}} -> {ok, prepare_aaci(ACI)};
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@@ -963,17 +990,39 @@ type(Name) -> binary_to_list(Name).
|
|||||||
%type(#{<<"map">> := {K, V}} -> {map, type(K), type(V)};
|
%type(#{<<"map">> := {K, V}} -> {map, type(K), type(V)};
|
||||||
%type(<<"string">>) -> string;
|
%type(<<"string">>) -> string;
|
||||||
|
|
||||||
coerce({integer, S}) ->
|
coerce({{ArgName, integer}, S}, {Good, Broken}) ->
|
||||||
list_to_integer(S);
|
try
|
||||||
coerce({address, S}) ->
|
N = list_to_integer(S),
|
||||||
{account_pubkey, Key} = aeser_api_encoder:decode(S),
|
{[N | Good], Broken}
|
||||||
{address, Key};
|
catch
|
||||||
coerce({contract, S}) ->
|
error:Reason -> {Good, [{ArgName, Reason} | Broken]}
|
||||||
aeser_api_encoder:decode(S);
|
end;
|
||||||
coerce({bool, S}) ->
|
coerce({{ArgName, address}, S}, {Good, Broken}) ->
|
||||||
S;
|
try
|
||||||
coerce({_, S}) ->
|
case aeser_api_encoder:decode(S) of
|
||||||
S.
|
{account_pubkey, Key} -> {[{address, Key} | Good], Broken};
|
||||||
|
_ -> {Good, [{ArgName, bad_pubkey} | Broken]}
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
error:Reason -> {Good, [{ArgName, Reason} | Broken]}
|
||||||
|
end;
|
||||||
|
coerce({{ArgName, contract}, S}, {Good, Broken}) ->
|
||||||
|
try
|
||||||
|
case aeser_api_encoder:decode(S) of
|
||||||
|
R = {contract_bytearray, _} -> {[R | Good], Broken};
|
||||||
|
_ -> {Good, [{ArgName, bad_contract} | Broken]}
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
error:Reason -> {Good, [{ArgName, Reason} | Broken]}
|
||||||
|
end;
|
||||||
|
coerce({{_, bool}, true}, {Good, Broken}) ->
|
||||||
|
{[true | Good], Broken};
|
||||||
|
coerce({{_, bool}, false}, {Good, Broken}) ->
|
||||||
|
{[false | Good], Broken};
|
||||||
|
coerce({{ArgName, bool}, _}, {Good, Broken}) ->
|
||||||
|
{Good, [{ArgName, not_bool} | Broken]};
|
||||||
|
coerce({_, S}, {Good, Broken}) ->
|
||||||
|
{[S | Good], Broken}.
|
||||||
|
|
||||||
|
|
||||||
-spec min_gas_price() -> integer().
|
-spec min_gas_price() -> integer().
|
||||||
@@ -993,11 +1042,30 @@ min_gas_price() ->
|
|||||||
1000000000.
|
1000000000.
|
||||||
|
|
||||||
|
|
||||||
encode_call_data({aaci, _Name, FunDefs}, Fun, Args) ->
|
encode_call_data({aaci, _, FunDefs}, Fun, Args) ->
|
||||||
ArgDef = maps:get(Fun, FunDefs),
|
case maps:find(Fun, FunDefs) of
|
||||||
Binding = lists:zip([element(2, D) || D <- ArgDef], Args),
|
{ok, ArgDef} -> encode_call_data2(ArgDef, Fun, Args);
|
||||||
Coerced = lists:map(fun coerce/1, Binding),
|
error -> {error, bad_fun_name}
|
||||||
aeb_fate_abi:create_calldata(Fun, Coerced).
|
end.
|
||||||
|
|
||||||
|
encode_call_data2(ArgDef, Fun, Args) ->
|
||||||
|
DefLength = length(ArgDef),
|
||||||
|
ArgLength = length(Args),
|
||||||
|
if
|
||||||
|
DefLength =:= ArgLength -> encode_call_data3(ArgDef, Fun, Args);
|
||||||
|
DefLength > ArgLength -> {error, too_few_args};
|
||||||
|
DefLength < ArgLength -> {error, too_many_args}
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_call_data3(ArgDef, Fun, Args) ->
|
||||||
|
Binding = lists:zip(ArgDef, Args),
|
||||||
|
case lists:foldl(fun coerce/2, {[], []}, Binding) of
|
||||||
|
{Coerced, []} ->
|
||||||
|
Reversed = lists:reverse(Coerced),
|
||||||
|
aeb_fate_abi:create_calldata(Fun, Reversed);
|
||||||
|
{_, Errors} ->
|
||||||
|
{error, {args, lists:reverse(Errors)}}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user