Call Contract Function
We can call the contract function using qubic-cli
, but unfortunately, we still need to manually craft the packet, send it, receive the response in hex, and then decode it into a readable struct. It's a bit of a tangled process—but let's see how to get it done.
Craft The Packet
Let's say we have a function called getStateNumber
in our deployed contract
Show getStateNumber
Function
struct getStateNumber_input
{
};
struct getStateNumber_output
{
uint64 stateNumber;
};
PUBLIC_FUNCTION(getStateNumber)
{
output.stateNumber = state.stateNumber;
}
So we can create the packet with this following code (added as a test case in your test)
Remember to #include "network_messages/contract.h"
in your test source first
static void byteToHex(const uint8_t* byte, char* hex, const int sizeInByte)
{
for (int i = 0; i < sizeInByte; i++)
{
snprintf(hex + i * 2, 3, "%02x", byte[i]);
}
}
static void hexToByte(const char* hex, uint8_t* byte, const int sizeInByte)
{
for (int i = 0; i < sizeInByte; i++)
{
sscanf(hex + i * 2, "%2hhx", &byte[i]);
}
}
TEST(Contract, CallFunction)
{
struct
{
RequestResponseHeader header;
RequestContractFunction rcf;
// Add your input here if needed
// Example: QNS::getStateNumber_input input;
} packet;
packet.header.setSize<sizeof(packet)>();
packet.header.randomizeDejavu();
packet.header.setType(RequestContractFunction::type);
// getStateNumber doesn't expect any input, so inputSize should be 0
// Example if you have input: packet.rcf.inputSize = sizeof(QNS::getStateNumber_input);
packet.rcf.inputSize = 0;
// In this case getStateNumber has been registered with id = 14
packet.rcf.inputType = 14;
// Change to your contract index
packet.rcf.contractIndex = QNS_CONTRACT_INDEX;
// Modify the input if needed
// Example: packet.input.stateNumber = 0; but in this case we don't need input
unsigned char* hexStr = new unsigned char[sizeof(packet) * 2 + 1];
byteToHex(reinterpret_cast<const uint8_t*>(&packet), reinterpret_cast<char*>(hexStr), sizeof(packet));
hexStr[sizeof(packet) * 2] = '\0'; // Null-terminate the string
cout << "Hex String: " << hexStr << endl;
cout << "Size: " << sizeof(packet) << endl;
delete[] hexStr;
}
Example output:
C:\Users\Admin>C:\Users\Admin\Projects\core\x64\Release\test.exe
Running main() from D:\a\_work\1\s\ThirdParty\googletest\googletest\src\gtest_main.cc
[==========] Running 140 tests from 30 test cases.
[----------] Global test environment set-up.
[----------] 1 test from Contract
[ RUN ] Contract.CallFunction
Hex String: 1000002ae0238c350d0000000e000000
Size: 16
Call Function
Then use these as inputs for qubic cli
qubic-cli.exe -nodeip 162.120.19.25 -nodeport 31841 -sendrawpacket 1000002ae0238c350d0000000e000000 16
Example output
qubic-cli.exe -nodeip 162.120.19.25 -nodeport 31841 -sendrawpacket 1000002ab25f5c7d0d0000000e000000 16
Received 16 bytes
1000002bb25f5c7d0000000000000000
Your actually response start from bytes 8 in this case is 0000000000000000
(stateNumber
is 0)
You can't use the same same input hex (dejavu) more then one. You need to re-generate the input hex then send again.
If your reponse is a complex struct, you should copy the hex then call hexToByte()
then cast these bytes to pointer of the output
struct