Skip to content

Commit

Permalink
feat: add readContract api endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
as-iotex authored and as-iotex committed Apr 17, 2022
1 parent 15e26b7 commit 4c26429
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/api/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,44 @@ RpcCallData Wallets::sendExecution(Host& host, const responsetypes::ActionCore_E
sprintf(body + strlen(body), "%s", base64Signature);
sprintf(body + strlen(body), R"(","encoding": "IOTEX_PROTOBUF"}})");

ret.body = body;
return ret;
}

RpcCallData Wallets::readContract(Host& host,
const responsetypes::Execution execution,
uint64_t gasLimit,
const IotexString callerAddress)
{
RpcCallData ret;

uint8_t data[execution.data.length() / 2];
memset(data, 0, sizeof(data));
char base64Data[sizeof(data) * 2]; // Double the size is enough for a base64 encoded message
signer.str2hex(execution.data.c_str(), data, sizeof(data));
encoder.base64_encode(data, sizeof(data), base64Data);

// Url
ret.url.reserve(URL_MAX_LEN);
ret.url += host.toString().c_str();
ret.url += "ReadContract";

// Body
char body[1024 + sizeof(base64Data)] = {0};
sprintf(body + strlen(body), R"({"execution": {"amount": ")");
sprintf(body + strlen(body), "%s", execution.amount);
sprintf(body + strlen(body), R"(")");
sprintf(body + strlen(body), R"(,"contract": ")");
sprintf(body + strlen(body), "%s", execution.contract);
sprintf(body + strlen(body), R"(","data": ")");
sprintf(body + strlen(body), "%s", base64Data);
sprintf(body + strlen(body), R"("})");
sprintf(body + strlen(body), R"(,"callerAddress": ")");
sprintf(body + strlen(body), "%s", callerAddress.c_str());
sprintf(body + strlen(body), R"(","gasLimit":")");
sprintf(body + strlen(body), "%lu", gasLimit);
sprintf(body + strlen(body), R"("})");

ret.body = body;
return ret;
}
2 changes: 2 additions & 0 deletions src/api/rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Wallets
const responsetypes::ActionCore_Execution execution,
const uint8_t senderPubKey[IOTEX_PUBLIC_KEY_SIZE],
const uint8_t signature[IOTEX_SIGNATURE_SIZE]);
static RpcCallData readContract(Host& host, const responsetypes::Execution execution,
uint64_t gasLimit, const IotexString callerAddress);
};

} // namespace rpc
Expand Down
23 changes: 23 additions & 0 deletions src/api/wallet/wallets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,28 @@ ResultCode Wallets::sendExecution(const uint8_t senderPubKey[IOTEX_PUBLIC_KEY_SI

IOTEX_DEBUG(logModule, "Sent execution request. Action hash: %s", response.hash);

return ret;
}

ResultCode Wallets::readContract(const responsetypes::Execution& execution,
const IotexString callerAddress,
uint64_t gasLimit,
ReadContractResponse* response)
{
ResultCode ret;
rpc::RpcCallData callData =
rpc::Wallets::readContract(this->host_, execution, gasLimit, callerAddress);
IotexString rspBody;

IOTEX_DEBUG(logModule, "Sending readContract request with body: %s", callData.body.c_str());

ret = http_->post(callData.url.c_str(), callData.body.c_str(), rspBody);
if(ret != ResultCode::SUCCESS)
return ret;

ret = response->fromJson(rspBody);
if(ret != ResultCode::SUCCESS)
return ret;

return ret;
}
17 changes: 17 additions & 0 deletions src/api/wallet/wallets.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ class IWallets : public Base
const responsetypes::ActionCore_Execution& transfer,
uint8_t hash[IOTEX_HASH_SIZE]) = 0;

/**
* @brief Reads a contract
*
* @param execution The execution data
* @param callerAddress The caller address
* @param gasLimit The gas limit
* @param[out] response The abi encoded response if successful
* @return ResultCode Success or an error code
*/
virtual ResultCode readContract(const responsetypes::Execution& execution,
const IotexString callerAddress, uint64_t gasLimit,
responsetypes::ReadContractResponse* response) = 0;

protected:
IWallets(Host& host, IHTTP& http) : Base(host, http)
{
Expand Down Expand Up @@ -130,6 +143,10 @@ class Wallets : public IWallets
const uint8_t signature[IOTEX_SIGNATURE_SIZE],
const responsetypes::ActionCore_Execution& transfer,
uint8_t hash[IOTEX_HASH_SIZE]) override;

virtual ResultCode readContract(const responsetypes::Execution& execution,
const IotexString callerAddress, uint64_t gasLimit,
responsetypes::ReadContractResponse* response) override;
}; // class Wallets : public IWallets

} // namespace api
Expand Down
108 changes: 108 additions & 0 deletions src/protobuf/pb_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,5 +667,113 @@ ResultCode SendExecutionResponse::fromJson(IotexString jsonString)

cJSON_Delete(data);

return ret;
}

ResultCode ReadContractResponse::fromJson(IotexString jsonString)
{
ResultCode ret = ResultCode::SUCCESS;
cJSON* data = cJSON_Parse(jsonString.c_str());
if(data == NULL)
{
cJSON_Delete(data);
return ResultCode::ERROR_JSON_PARSE;
}

const cJSON* rspData = cJSON_GetObjectItemCaseSensitive(data, "data");
ret = SetValueFromJsonObject(rspData, CppType::STRING, (void*)&(this->data));
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}

// Receipt
const cJSON* receipt = cJSON_GetObjectItemCaseSensitive(data, "receipt");
// The server serializes the values as string even if they are integers
// cJSON fails if trying to parse a stringified int as an int
// So we use a tmp string to convert them
IotexString tmp;

// Status
const cJSON* status = cJSON_GetObjectItemCaseSensitive(receipt, "status");
ret = SetValueFromJsonObject(status, CppType::STRING, &tmp);
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
this->receipt.status = atol(tmp.c_str());

// blkHeight
const cJSON* blkHeight = cJSON_GetObjectItemCaseSensitive(receipt, "blkHeight");
ret = SetValueFromJsonObject(blkHeight, CppType::STRING, &tmp);
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
this->receipt.blkHeight = atol(tmp.c_str());

// actHash
const cJSON* hash = cJSON_GetObjectItemCaseSensitive(receipt, "actHash");
memset(this->receipt.actHash, 0, sizeof(this->receipt.actHash));
ret = SetValueFromJsonObject(hash, CppType::C_STRING, (void*)&(this->receipt.actHash), IOTEX_HASH_STRLEN);
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}

// gasConsumed
const cJSON* gasConsumed = cJSON_GetObjectItemCaseSensitive(receipt, "gasConsumed");
ret = SetValueFromJsonObject(gasConsumed, CppType::STRING, &tmp);
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
this->receipt.gasConsumed = atol(tmp.c_str());

// Following fields are optional
// contractAddress
const cJSON* contractAddress = cJSON_GetObjectItemCaseSensitive(receipt, "contractAddress");
if (contractAddress)
{
memset(this->receipt.contractAddress, 0, sizeof(this->receipt.contractAddress));
ret = SetValueFromJsonObject(contractAddress, CppType::C_STRING, (void*)&(this->receipt.contractAddress), IOTEX_ADDRESS_STRLEN);
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
}

// executionRevertMsg
const cJSON* executionRevertMsg = cJSON_GetObjectItemCaseSensitive(receipt, "executionRevertMsg");
if (executionRevertMsg)
{
ret = SetValueFromJsonObject(executionRevertMsg, CppType::STRING, (void*)&(this->receipt.executionRevertMsg));
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
}

// gasConsumed
const cJSON* txIndex = cJSON_GetObjectItemCaseSensitive(receipt, "txIndex");
if (txIndex)
{
ret = SetValueFromJsonObject(txIndex, CppType::UINT32, (void*)&(this->receipt.txIndex));
if(ret != ResultCode::SUCCESS)
{
cJSON_Delete(data);
return ret;
}
}

cJSON_Delete(data);

return ret;
}
25 changes: 25 additions & 0 deletions src/protobuf/pb_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,31 @@ struct SendExecutionResponse
char hash[IOTEX_HASH_C_STRING_SIZE];
};

struct Receipt
{
public:
ResultCode fromJson(IotexString jsonString);

public:
uint64_t status;
uint64_t blkHeight;
char actHash[IOTEX_HASH_C_STRING_SIZE];
uint64_t gasConsumed;
char contractAddress[IOTEX_ADDRESS_C_STRING_SIZE];
IotexString executionRevertMsg;
uint32_t txIndex;
};

struct ReadContractResponse
{
public:
ResultCode fromJson(IotexString jsonString);

public:
IotexString data;
Receipt receipt;
};

// JSON Objects - unused

struct AccountMetaJsonObject
Expand Down

0 comments on commit 4c26429

Please sign in to comment.