mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
295 lines
10 KiB
C++
295 lines
10 KiB
C++
|
|
#include "HederaAccount.h"
|
|
#include "NodeServer.h"
|
|
#include "CryptoKey.h"
|
|
#include "../model/hedera/Query.h"
|
|
//#include "../model/hedera/Tr"
|
|
#include "HederaRequest.h"
|
|
|
|
#include "../SingletonManager/ErrorManager.h"
|
|
|
|
using namespace Poco::Data::Keywords;
|
|
|
|
namespace controller {
|
|
|
|
HederaAccount::HederaAccount(model::table::HederaAccount* dbModel)
|
|
{
|
|
mDBModel = dbModel;
|
|
}
|
|
|
|
HederaAccount::~HederaAccount()
|
|
{
|
|
}
|
|
|
|
Poco::AutoPtr<HederaAccount> HederaAccount::create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/, ServerConfig::HederaNetworkType type/* = HEDERA_MAINNET*/)
|
|
{
|
|
auto db = new model::table::HederaAccount(user_id, account_hedera_id, account_key_id, balance, type);
|
|
auto group = new HederaAccount(db);
|
|
return Poco::AutoPtr<HederaAccount>(group);
|
|
}
|
|
|
|
std::vector<Poco::AutoPtr<HederaAccount>> HederaAccount::load(const std::string& fieldName, int fieldValue)
|
|
{
|
|
auto db = new model::table::HederaAccount();
|
|
auto hedera_account_list = db->loadFromDB<int, model::table::HederaAccountTuple>(fieldName, fieldValue, 2);
|
|
std::vector<Poco::AutoPtr<HederaAccount>> resultVector;
|
|
resultVector.reserve(hedera_account_list.size());
|
|
for (auto it = hedera_account_list.begin(); it != hedera_account_list.end(); it++) {
|
|
//mHederaID
|
|
auto db = new model::table::HederaAccount(*it);
|
|
auto hedera_account = new HederaAccount(db);
|
|
resultVector.push_back(hedera_account);
|
|
}
|
|
return resultVector;
|
|
}
|
|
|
|
Poco::AutoPtr<HederaAccount> HederaAccount::load(int id)
|
|
{
|
|
auto db = new model::table::HederaAccount();
|
|
if (1 == db->loadFromDB("id", id)) {
|
|
return new HederaAccount(db);
|
|
}
|
|
db->release();
|
|
return nullptr;
|
|
}
|
|
|
|
Poco::AutoPtr<controller::HederaId> HederaAccount::getHederaId()
|
|
{
|
|
if (mHederaID.isNull()) {
|
|
mHederaID = HederaId::load(getModel()->getAccountHederaId());
|
|
}
|
|
return mHederaID;
|
|
}
|
|
|
|
Poco::AutoPtr<HederaAccount> HederaAccount::load(Poco::AutoPtr<controller::HederaId> hederaId)
|
|
{
|
|
if (!hederaId->isExistInDB()) return nullptr;
|
|
|
|
auto db = new model::table::HederaAccount();
|
|
auto result_count = db->loadFromDB("account_hedera_id", hederaId->getModel()->getID());
|
|
if (1 == result_count) {
|
|
return new HederaAccount(db);
|
|
}
|
|
// maybe change later to using error manager and send email
|
|
printf("[HederaAccount::load] result_count not expected: %d\n", result_count);
|
|
return nullptr;
|
|
}
|
|
|
|
Poco::AutoPtr<HederaAccount> HederaAccount::pick(ServerConfig::HederaNetworkType networkType, bool encrypted/* = false*/, int user_id/* = 0*/)
|
|
{
|
|
auto cm = ConnectionManager::getInstance();
|
|
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
|
Poco::Data::Statement select(session);
|
|
|
|
Poco::Tuple<int, int, int, int, Poco::UInt64, Poco::UInt64, Poco::UInt64, Poco::UInt64> result_tuple;
|
|
int crypto_key_type = encrypted ? model::table::KEY_TYPE_ED25519_HEDERA_ENCRYPTED : model::table::KEY_TYPE_ED25519_HEDERA_CLEAR;
|
|
int network_type_int = (int)networkType;
|
|
|
|
select
|
|
<< "SELECT account.id, account.user_id, account.account_hedera_id, account.account_key_id, account.balance, i.shardNum, i.realmNum, i.num "
|
|
<< "FROM hedera_accounts as account "
|
|
<< "JOIN hedera_ids as i ON(i.id = account_hedera_id) "
|
|
<< "JOIN crypto_keys as k ON(k.id = account.account_key_id) "
|
|
<< "WHERE account.network_type = ? "
|
|
<< "AND k.crypto_key_type_id = ? ";
|
|
|
|
if (user_id > 0) {
|
|
select << " AND account.user_id = ? ";
|
|
}
|
|
select << "ORDER BY RAND() LIMIT 1 "
|
|
, into(result_tuple), use(network_type_int) , use(crypto_key_type);
|
|
|
|
if (user_id > 0) {
|
|
select, use(user_id);
|
|
}
|
|
|
|
try {
|
|
select.executeAsync();
|
|
select.wait();
|
|
auto result_count = select.rowsExtracted();
|
|
if (1 == result_count) {
|
|
auto db = new model::table::HederaAccount(
|
|
result_tuple.get<1>(), result_tuple.get<2>(), result_tuple.get<3>(),
|
|
result_tuple.get<4>(), networkType
|
|
);
|
|
db->setID(result_tuple.get<0>());
|
|
Poco::AutoPtr<HederaAccount> hedera_account(new HederaAccount(db));
|
|
auto hedera_id_db = new model::table::HederaId(result_tuple.get<5>(), result_tuple.get<6>(), result_tuple.get<7>());
|
|
Poco::AutoPtr<HederaId> hedera_id(new HederaId(hedera_id_db));
|
|
hedera_account->setHederaId(hedera_id);
|
|
return hedera_account;
|
|
}
|
|
else if(result_count > 1) {
|
|
printf("[HederaAccount::pick] extracted rows not like expected\n");
|
|
}
|
|
}
|
|
catch (Poco::Exception& ex) {
|
|
auto em = ErrorManager::getInstance();
|
|
static const char* function_name = "HederaAccount::pick";
|
|
printf("exception: %s\n", ex.displayText().data());
|
|
em->addError(new ParamError(function_name, "mysql error: ", ex.displayText()));
|
|
em->addError(new ParamError(function_name, "network type: ", networkType));
|
|
em->addError(new ParamError(function_name, "encrypted: ", (int)encrypted));
|
|
em->sendErrorsAsEmail();
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
std::vector<Poco::AutoPtr<HederaAccount>> HederaAccount::listAll()
|
|
{
|
|
auto db = new model::table::HederaAccount();
|
|
std::vector<model::table::HederaAccountTuple> group_list;
|
|
// throw an unresolved external symbol error
|
|
group_list = db->loadAllFromDB<model::table::HederaAccountTuple>();
|
|
|
|
// work around for not working call to loadAllFromDB
|
|
/*auto cm = ConnectionManager::getInstance();
|
|
|
|
Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER));
|
|
|
|
select << "SELECT id, alias, name, url, description FROM " << db->getTableName()
|
|
, Poco::Data::Keywords::into(group_list);
|
|
|
|
size_t resultCount = 0;
|
|
try {
|
|
resultCount = select.execute();
|
|
}
|
|
catch (Poco::Exception& ex) {
|
|
printf("[Group::listAll] poco exception: %s\n", ex.displayText().data());
|
|
}
|
|
//*/ //work around end
|
|
std::vector<Poco::AutoPtr<HederaAccount>> resultVector;
|
|
|
|
resultVector.reserve(group_list.size());
|
|
for (auto it = group_list.begin(); it != group_list.end(); it++) {
|
|
Poco::AutoPtr<HederaAccount> group_ptr(new HederaAccount(new model::table::HederaAccount(*it)));
|
|
resultVector.push_back(group_ptr);
|
|
}
|
|
return resultVector;
|
|
}
|
|
|
|
Poco::AutoPtr<controller::CryptoKey> HederaAccount::getCryptoKey() const
|
|
{
|
|
auto model = getModel();
|
|
return controller::CryptoKey::load(model->getCryptoKeyId());
|
|
}
|
|
|
|
bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr<controller::User> user)
|
|
{
|
|
static const char* functionName = "HederaAccount::updateBalanceFromHedera";
|
|
|
|
if (user.isNull() || !user->getModel()) {
|
|
printf("[%s] invalid user\n", functionName);
|
|
return false;
|
|
}
|
|
|
|
auto account_model = getModel();
|
|
auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType()));
|
|
if (hedera_node.url == "") {
|
|
addError(new Error("Hedera Node", "no hedera node found"));
|
|
return false;
|
|
}
|
|
auto crypto_key = controller::CryptoKey::load(account_model->getCryptoKeyId());
|
|
if (crypto_key.isNull()) {
|
|
addError(new Error("Keys", "could not found crypto key for account"));
|
|
printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId());
|
|
return false;
|
|
}
|
|
auto hedera_key_pair = crypto_key->getKeyPair(user);
|
|
if (!hedera_key_pair) {
|
|
addError(new Error("Keys", "error decrypting private key"));
|
|
printf("[%s] error decrypting private key with id: %d, with user: %d\n", functionName, account_model->getCryptoKeyId(), user->getModel()->getID());
|
|
return false;
|
|
}
|
|
|
|
auto query = model::hedera::Query::getBalance(getHederaId(), hedera_node);
|
|
|
|
if (!query) {
|
|
printf("[%s] error creating query\n", functionName);
|
|
}
|
|
query->sign(std::move(hedera_key_pair));
|
|
|
|
HederaRequest request;
|
|
model::hedera::Response response;
|
|
try {
|
|
if (HEDERA_REQUEST_RETURN_OK == request.request(query, &response) && proto::OK == response.getResponseCode()) {
|
|
account_model->updateIntoDB("balance", response.getAccountBalance());
|
|
}
|
|
else {
|
|
addError(new Error("Hedera", "Hedera request failed"));
|
|
addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode())));
|
|
}
|
|
//request.requestViaPHPRelay(query);
|
|
}
|
|
catch (Poco::Exception& ex) {
|
|
printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data());
|
|
}
|
|
|
|
if (0 == errorCount() && 0 == request.errorCount()) {
|
|
return true;
|
|
}
|
|
getErrors(&request);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HederaAccount::hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance)
|
|
{
|
|
auto account_model = getModel();
|
|
auto new_key_pair = KeyPairHedera::create();
|
|
auto transaction_body = createTransactionBody();
|
|
//CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod);
|
|
model::hedera::CryptoCreateTransaction create_transaction(new_key_pair->getPublicKey(), initialBalance, autoRenewPeriodSeconds);
|
|
transaction_body->setCryptoCreate(create_transaction);
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HederaAccount::changeEncryption(Poco::AutoPtr<controller::User> user)
|
|
{
|
|
assert(!user.isNull() && user->getModel());
|
|
auto model = getModel();
|
|
assert(!model.isNull());
|
|
|
|
if (user->getModel()->getID() != model->getUserId()) {
|
|
addError(new Error("Hedera Account", "wrong user"));
|
|
return false;
|
|
}
|
|
auto crypto_key = controller::CryptoKey::load(model->getCryptoKeyId());
|
|
if (crypto_key.isNull()) {
|
|
addError(new Error("Hedera Account", "couldn't find crypto key"));
|
|
return false;
|
|
}
|
|
bool result = crypto_key->changeEncryption(user);
|
|
getErrors(crypto_key);
|
|
return result;
|
|
|
|
}
|
|
|
|
std::unique_ptr<model::hedera::TransactionBody> HederaAccount::createTransactionBody()
|
|
{
|
|
auto account_model = getModel();
|
|
auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType()));
|
|
auto hedera_id = getHederaId();
|
|
if (hedera_id.isNull()) {
|
|
return nullptr;
|
|
}
|
|
return std::make_unique<model::hedera::TransactionBody>(mHederaID, hedera_node);
|
|
}
|
|
|
|
|
|
std::string HederaAccount::toShortSelectOptionName()
|
|
{
|
|
std::stringstream ss;
|
|
auto model = getModel();
|
|
ss << model::table::HederaAccount::hederaNetworkTypeToString((ServerConfig::HederaNetworkType)model->getNetworkType()) << " ";
|
|
ss << getHederaId()->getModel()->toString() << " " << ((double)model->getBalance() / 100000000.0) << " Hbar";
|
|
return ss.str();
|
|
}
|
|
|
|
}
|
|
|