Across SDKs, we've got the following functionalities:
ContractCallQuery - returning a result of executing a function
ContractCreateFlow - which is returning only receipt
ContractCreateTransaction - which is returning only the receipt
ContractExecuteTransaction - which returns only receipt, but not a result of the call (if we call a function)
All those flows use ContractFunctionParameters().
In the ContractFunctionParameters() we’ve got the following methods:
addString
addStringArray
addBytes
addBytes32
addBytesArray
addBytes32Array
addBool
addInt8
addUint8
addInt16
addUint16
and so on…. a file with 1700 lines and a lot of methods, switch cases, and IFs.
The workflow is as follows:
We are calling some of the “add methods” of ContractFunctionParameters
Then, we call _addParam
Then we call argumentToBytes and convert the passing params to the function to bytes (Uint8Array)
Then we got ContractFunctionSelectorfile with 1400 lines of code.
We are using that file with all the helper methods inside to create the signature of the function.
For example:
We’ve got ArgumentType to integers
We’ve got different methods such as addString which returns the signature of the function
We’ve got solidityTypeToString where we are transpile solidity types to string, for example:
case ArgumentType.uint8:
s = "uint8";
This all is created because we are not requiring the ABI of a contract when we are doing:
ContractCallQuery
ContractCreateFlow
ContractCreateTransaction
ContractExecuteTransaction
….etc
The above workflow assumes that the user will know the exact parameters that a function is accepting when performing the above calls. According to my opinion, this could lead to errors and unpredicted behavior because of the missing or wrong passed params.
We can use the ABI of the contract and then pass params. We can leave the transforming of the contract function params to bytes to the SDK and then decode them back to the SDK.
For example, when we are retrieving results from:
ContractFunctionResult
we need to decode manually the response again using similar functions as in ContractFunctionParameters :
getUint40 and to pass the index of the returned param of the contract function
As you can see, this is not convenient, because the users must know the signature of the functions (what is accepting and what is returning).
Solution
Encoding and passing data to contract
We can add the following setter and function params:
setAbi()
callFunction
setAbi will receive the ABI of the compiled contract, for example:
.setAbi(setDataContract.abi)
callFunction will receive the signature of the function together with the passed params, for example:
callFunction("setMultipleMessages", [
"New Message",
"Second New Message",
]);
Decoding and retrieving data from the contract
I’ve implemented a method called:
const result = txResponse.getResult(["uint32", "uint64", "string"]);
Where you can pass the signature of the function (from the ABI) and use it to decode and return the result.
The method getResult is tested in production (actually it is released because a lof of people had problems decoding data from contract calls).
Alternatives
Notes from the last meeting:
For passing the input:
Maybe the whole ABI is too much information
We can use a similar approach to the getResult function with something like:
setValue (with passing the signature)
setABIFunction (not sure the “ABI” terminology is used correctly here)
setFunctionSignature
For getting the output:
we can keep the method getResult passing the function signature
For different SDKs:
We need to consider using the ready-to-be-used solutions for ABI encode/decode or write our own (this will be quite big enough because the SDKs are trying now to do it on their own and the result is that only the main cases (straightforward) are supported.
Problem
Across SDKs, we've got the following functionalities:
All those flows use
ContractFunctionParameters()
. In theContractFunctionParameters()
we’ve got the following methods:and so on…. a file with
1700
lines and a lot of methods, switch cases, and IFs.The workflow is as follows:
ContractFunctionParameters
_addParam
argumentToBytes
and convert the passing params to the function to bytes (Uint8Array
)Then we got
ContractFunctionSelector
file with1400
lines of code.We are using that file with all the helper methods inside to create the signature of the function.
For example:
ArgumentType
to integersaddString
which returns the signature of the functionsolidityTypeToString
where we are transpile solidity types to string, for example:This all is created because we are not requiring the ABI of a contract when we are doing:
The above workflow assumes that the user will know the exact parameters that a function is accepting when performing the above calls. According to my opinion, this could lead to errors and unpredicted behavior because of the missing or wrong passed params.
We can use the ABI of the contract and then pass params. We can leave the transforming of the contract function params to bytes to the SDK and then decode them back to the SDK.
For example, when we are retrieving results from:
we need to decode manually the response again using similar functions as in
ContractFunctionParameters
:getUint40
and to pass the index of the returned param of the contract functionAs you can see, this is not convenient, because the users must know the signature of the functions (what is accepting and what is returning).
Solution
Encoding and passing data to contract
Decoding and retrieving data from the contract
I’ve implemented a method called:
const result = txResponse.getResult(["uint32", "uint64", "string"]);
Where you can pass the signature of the function (from the ABI) and use it to decode and return the result.
The method
getResult
is tested in production (actually it is released because a lof of people had problems decoding data from contract calls).Alternatives
Notes from the last meeting:
For passing the input:
getResult
function with something like:For getting the output:
getResult
passing the function signatureFor different SDKs:
C++
- [Silkworm](https://github.com/torquem-ch/silkworm) (still WIP). RequiresC++20
compiler, which does not work at the moment becauseHedera C++ SDK
usesC++17
(to be checked)