Update code for sending transaction over hedera

This commit is contained in:
Dario 2020-09-14 21:09:18 +02:00
parent eaf95f87e4
commit 7449f73e89
35 changed files with 1009 additions and 242 deletions

View File

@ -96,6 +96,24 @@ KeyPairHedera::~KeyPairHedera()
}
}
KeyPairHedera* KeyPairHedera::create()
{
/*
The crypto_sign_keypair() function randomly generates a secret key and a corresponding public key.
The public key is put into pk (crypto_sign_PUBLICKEYBYTES bytes)
and the secret key into sk (crypto_sign_SECRETKEYBYTES bytes).
*/
assert(getPublicKeySize() == crypto_sign_PUBLICKEYBYTES);
auto mm = MemoryManager::getInstance();
auto private_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES);
auto public_key = mm->getFreeMemory(getPublicKeySize());
crypto_sign_keypair(*public_key, *private_key);
return new KeyPairHedera(private_key, public_key);
}
void KeyPairHedera::createKeyFromSeed(const unsigned char* seed, size_t seedSize)
{

View File

@ -26,6 +26,9 @@ public:
KeyPairHedera(const unsigned char* privateKey, size_t privateKeySize, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0);
KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr);
KeyPairHedera(const std::vector<unsigned char>& privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0);
static KeyPairHedera* create();
~KeyPairHedera();
@ -43,12 +46,12 @@ public:
const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;}
inline bool isTheSame(const KeyPairHedera& b) const {
return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE);
return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, getPublicKeySize());
}
inline bool isTheSame(const unsigned char* pubkey) const {
if (!pubkey)
return false;
return 0 == sodium_memcmp(mPublicKey, pubkey, ed25519_pubkey_SIZE);
return 0 == sodium_memcmp(mPublicKey, pubkey, getPublicKeySize());
}
//! \return 0 if the same
//! \return -1 if not the same

View File

@ -45,6 +45,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
auto sm = SessionManager::getInstance();
auto mm = MemoryManager::getInstance();
auto user = mSession->getNewUser();
int auto_renew_period = 604800; // 7 Tage
int auto_renew_account = 0;
double initial_balance = 0.0;
Profiler hedera_time;
std::string hedera_time_string;
@ -80,8 +83,11 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
if(action == "updateBalance")
{
hedera_time.reset();
query_hedera_account->hederaAccountGetBalance(user);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
if(query_hedera_account->hederaAccountGetBalance(user)) {
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
} else {
addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string()));
}
}
else if(action == "changeEncryption")
{
@ -90,113 +96,150 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
}
}
}
else if(!form.empty()) // add
else if(!form.empty()) // add or create
{
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
auto creationButton = form.get("create","");
if(creationButton != "") {
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
int networkType = 0;
MemoryBin* private_key = nullptr;
MemoryBin* public_key = nullptr;
// validate
if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "shard num not integer"));
} else {
if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting shardNumString to int"));
}
}
if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "realm num not integer"));
} else {
if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting realmNumString to int"));
}
}
if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "num not integer"));
} else {
if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting num to int"));
}
}
if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "private key not hex"));
}
if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "public key not hex"));
}
if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Network Type", "not integer"));
} else {
if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting network type to int"));
}
if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) {
addError(new Error("Network Type", "invalid value"));
}
}
if(0 == errorCount()) {
auto hedera_id = controller::HederaId::create(shardNum, realmNum, num);
// collect
auto auto_renew_account_string = form.get("account-auto-renew-account", "0");
auto auto_renew_period_string = form.get("account-auto-renew-period", "604800");
auto account_initial_balance_string = form.get("account-initial-balance", "0");
private_key = DataTypeConverter::hexToBin(privateKeyString);
public_key = DataTypeConverter::hexToBin(publicKeyString);
KeyPairHedera key_pair(private_key, public_key);
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account", "auto renew account id not an integer"));
} else {
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int convert error", "Error converting auto renew account id to int"));
}
}
mm->releaseMemory(private_key);
mm->releaseMemory(public_key);
}
if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account", "auto renew period not an integer"));
} else {
if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int convert error", "Error converting auto renew period to int"));
}
}
if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) {
addError(new Error("Account", "initial balance not an decimal"));
} else {
if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Double convert error", "Error converting initial balance to double"));
}
}
if(0 == errorCount())
{
}
} else {
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
int networkType = 0;
MemoryBin* private_key = nullptr;
MemoryBin* public_key = nullptr;
// validate
if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "shard num not integer"));
} else {
if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting shardNumString to int"));
}
}
if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "realm num not integer"));
} else {
if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting realmNumString to int"));
}
}
if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "num not integer"));
} else {
if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting num to int"));
}
}
if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "private key not hex"));
}
if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "public key not hex"));
}
if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Network Type", "not integer"));
} else {
if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting network type to int"));
}
if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) {
addError(new Error("Network Type", "invalid value"));
}
}
if(0 == errorCount()) {
auto hedera_id = controller::HederaId::create(shardNum, realmNum, num);
private_key = DataTypeConverter::hexToBin(privateKeyString);
public_key = DataTypeConverter::hexToBin(publicKeyString);
KeyPairHedera key_pair(private_key, public_key);
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
} else {
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
}
}
mm->releaseMemory(private_key);
mm->releaseMemory(public_key);
}
}
}
if(!query_hedera_account.isNull()) {
getErrors(query_hedera_account);
@ -262,7 +305,15 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t<div class=\"content\">";
// end include header_large.cpsp
responseStream << "\n";
#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << "<style type=\"text/css\">\n";
responseStream << "\t.center-form-form .input-40 {\n";
responseStream << "\t\tmargin-left:0;\n";
responseStream << "\t\twidth:40%;\n";
responseStream << "\t\tdisplay:inline-block;\n";
responseStream << "\t}\n";
responseStream << "\t\n";
responseStream << "</style>\n";
#line 238 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( getErrorsHtml() );
responseStream << "\n";
responseStream << "<div class=\"center-form-container\">\n";
@ -280,7 +331,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t\t\t<div class=\"cell header-cell c5\">Aktionen</div>\n";
responseStream << "\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 254 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) {
auto hedera_account_model = (*it)->getModel();
auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID());
@ -288,59 +339,63 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
if(hedera_account_model->getUserId() == user->getModel()->getID()) {
changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID());
}
auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted();
//printf("change encryption: %s\n", changeEncryption.data());
responseStream << "\n";
responseStream << "\t\t\t\t<div class=\"row\">\n";
responseStream << "\t\t\t\t\t<div class=\"cell c2\">";
#line 213 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 265 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( (*it)->getHederaId()->getModel()->toString() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 266 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( hedera_account_model->getBalanceDouble() );
responseStream << " hbar</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c2\">";
#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 267 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 216 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" );
responseStream << "\t\t\t\t\t<div class=\"cell c3 ";
#line 268 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( isEncrypted ? "success-color" : "alert-color");
responseStream << "\">";
#line 268 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( isEncrypted ? "Ja": "Nein" );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell c3\">";
#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 269 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( hedera_account_model->getUpdatedString() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<button class=\"form-button\" title=\"Anfrage an Hedera, aktuell kostenlos\" onclick=\"window.location.href='";
#line 218 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 270 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( updateUrl );
responseStream << "'\" >\n";
responseStream << "\t\t\t\t\t\tUpdate Balance\n";
responseStream << "\t\t\t\t\t</button>\n";
responseStream << "\t\t\t\t\t";
#line 221 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 273 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
if(changeEncryption != "") { responseStream << "\n";
responseStream << "\t\t\t\t\t\t<button class=\"form-button\" title=\"Ändere den Verschlüsselungsstatus des Private Keys in der Datenbank\" onclick=\"window.location.href='";
#line 222 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 274 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( changeEncryption );
responseStream << "'\">\n";
responseStream << "\t\t\t\t\t\t\tChange Encryption\n";
responseStream << "\t\t\t\t\t\t</button>\n";
responseStream << "\t\t\t\t\t";
#line 225 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 277 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 227 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 279 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t</div>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-title\">\n";
responseStream << "\t <h3>Einen neuen Account anlegen</h3>\n";
responseStream << "\t <h3>Ein existierenden Account eintragen</h3>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-form\">\n";
responseStream << "\t\t<form method=\"POST\" action=\"";
#line 234 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 286 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/hedera_account\">\n";
responseStream << "\t\t\t<label class=\"form-label\">Hedera Account ID</label>\n";
@ -356,25 +411,75 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-network-type\">Network Type</label>\n";
responseStream << "\t\t\t<select class=\"form-control\" name=\"account-network-type\" id=\"account-network-type\">\n";
responseStream << "\t\t\t";
#line 247 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 299 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
for(int i = 0; i < model::table::HEDERA_NET_COUNT; i++) { responseStream << "\n";
responseStream << "\t\t\t\t<option value=\"";
#line 248 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 300 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( i );
responseStream << "\">";
#line 248 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 300 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString((model::table::HederaNetworkType)i) );
responseStream << "</option>\n";
responseStream << "\t\t\t";
#line 249 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
#line 301 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t\t</select>\n";
responseStream << "\t\t\t<input class=\"center-form-submit form-button\" type=\"submit\" name=\"submit\" value=\"";
#line 251 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << "\t\t\t<input class=\"center-form-submit form-button\" type=\"submit\" name=\"add\" value=\"";
#line 303 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( gettext("Add Account") );
responseStream << "\">\n";
responseStream << "\t\t</form>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-title\">\n";
responseStream << "\t\t<h3>Ein neuen Account anlegen</h3>\n";
responseStream << "\t\t<p>Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.</p>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-form\">\n";
responseStream << "\t\t<form method=\"POST\" action=\"";
#line 311 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/hedera_account\">\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-auto-renew-account\">Auto Renew and Founding Hedera Account</label>\n";
responseStream << "\t\t\t<select name=\"account-auto-renew-account\" id=\"account-auto-renew-account\">\n";
responseStream << "\t\t\t\t";
#line 314 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) {
auto model = (*it)->getModel();
responseStream << "\n";
responseStream << "\t\t\t\t\t<option title=\"";
#line 317 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model->toString() );
responseStream << "\" value=\"";
#line 317 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( model->getID() );
responseStream << "\" ";
#line 317 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
if(auto_renew_account == model->getID()) { responseStream << "selected=\"selected\"";
#line 317 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << ">";
#line 317 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( (*it)->toShortSelectOptionName() );
responseStream << "</option>\n";
responseStream << "\t\t\t\t";
#line 318 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
} responseStream << "\n";
responseStream << "\t\t\t</select>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-auto-renew-period\">Auto Renew Period in seconds</label>\n";
responseStream << "\t\t\t<div><input class=\"form-control input-40\" id=\"account-auto-renew-period\" value=\"";
#line 321 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( auto_renew_period );
responseStream << "\" type=\"number\" name=\"account-auto-renew-period\"/><span style=\"margin-left:8px\" id=\"readable-auto-renew-period\"></span><div>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"account-initial-balance\">Initial Balance for new Account (taken from founding account)</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"account-initial-balance\" name=\"account-initial-balance\" type=\"number\" step=\"0.00000001\" value=\"";
#line 323 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( std::to_string(initial_balance) );
responseStream << "\" />\n";
responseStream << "\t\t\t<input class=\"center-form-submit form-button\" type=\"submit\" name=\"create\" value=\"";
#line 324 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( gettext("Create Account") );
responseStream << "\">\n";
responseStream << "\t\t</form>\n";
responseStream << "\t</div>\n";
responseStream << "</div>\n";
// begin include footer.cpsp
responseStream << " <div class=\"center-bottom\">\n";
@ -400,5 +505,18 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request
responseStream << "</html>";
// end include footer.cpsp
responseStream << "\n";
responseStream << "<script type=\"text/javascript\" src=\"";
#line 329 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "/js/time_calculations.js\"></script>\n";
responseStream << "<script type=\"text/javascript\">\n";
responseStream << "\tvar input = document.getElementById(\"account-auto-renew-period\");\n";
responseStream << "\tvar span = document.getElementById(\"readable-auto-renew-period\");\n";
responseStream << "\tspan.innerHTML = '~ ' + getExactTimeDuration(input.value);\n";
responseStream << "\tinput.addEventListener('keyup', function(e) {\n";
responseStream << "\t\tspan.innerHTML = '~ ' + getExactTimeDuration(input.value);\n";
responseStream << "\t});\n";
responseStream << "\t\n";
responseStream << "</script>\n";
if (_compressResponse) _gzipStream.close();
}

View File

@ -0,0 +1,17 @@
#include "HederaTaskManager.h"
HederaTaskManager* HederaTaskManager::getInstance()
{
static HederaTaskManager one;
return &one;
}
HederaTaskManager::HederaTaskManager()
{
}
HederaTaskManager::~HederaTaskManager()
{
}

View File

@ -0,0 +1,23 @@
#ifndef __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H
#define __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H
/*!
* @author: Dario Rekowski
*
* @date: 11.09.2020
*
* @brief: Manage Hedera Task, waiting on Consensus for Hedera Transactions
*
*/
class HederaTaskManager
{
public:
~HederaTaskManager();
static HederaTaskManager* getInstance();
protected:
HederaTaskManager();
};
#endif //__GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H

View File

@ -48,6 +48,7 @@ bool SessionManager::init()
case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break;
case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break;
case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break;
case VALIDATE_ONLY_DECIMAL: mValidations[i] = new Poco::RegularExpression("^[0-9]*(\.|,)[0-9]*$"); break;
case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break;
//case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break;
case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break;

View File

@ -29,6 +29,7 @@ enum SessionValidationTypes {
VALIDATE_PASSPHRASE,
VALIDATE_HAS_NUMBER,
VALIDATE_ONLY_INTEGER,
VALIDATE_ONLY_DECIMAL,
VALIDATE_ONLY_HEX,
VALIDATE_ONLY_URL,
VALIDATE_HAS_SPECIAL_CHARACTER,

View File

@ -3,8 +3,13 @@
#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)
@ -54,6 +59,51 @@ namespace controller {
return nullptr;
}
Poco::AutoPtr<HederaAccount> HederaAccount::pick(model::table::HederaNetworkType networkType, bool encrypted/* = false*/)
{
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;
//id, user_id, account_hedera_id, account_key_id, balance, network_type, updated
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.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 = ? ORDER BY RAND() LIMIT 1 ",
into(result_tuple), use(networkType), use(crypto_key_type);
try {
select.executeAsync();
select.wait();
if (1 == select.rowsExtracted()) {
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;
}
}
catch (Poco::Exception& ex) {
auto em = ErrorManager::getInstance();
static const char* function_name = "HederaAccount::pick";
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();
@ -140,11 +190,27 @@ namespace controller {
printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data());
}
getErrors(&request);
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());
@ -166,6 +232,13 @@ namespace controller {
}
std::unique_ptr<model::hedera::TransactionBody> HederaAccount::createTransactionBody()
{
auto account_model = getModel();
auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType()));
return std::make_unique<model::hedera::TransactionBody>(mHederaID, hedera_node);
}
std::string HederaAccount::toShortSelectOptionName()
{

View File

@ -5,6 +5,8 @@
#include "User.h"
#include "../model/table/HederaAccount.h"
#include "../model/hedera/TransactionBody.h"
#include "Poco/SharedPtr.h"
#include "TableControllerBase.h"
@ -21,6 +23,8 @@ namespace controller {
static std::vector<Poco::AutoPtr<HederaAccount>> load(const std::string& fieldName, int fieldValue);
static Poco::AutoPtr<HederaAccount> load(Poco::AutoPtr<controller::HederaId> hederaId);
static std::vector<Poco::AutoPtr<HederaAccount>> listAll();
//! \brief for picking a account for paying transaction, mostly consensusSendMessage
static Poco::AutoPtr<HederaAccount> pick(model::table::HederaNetworkType networkType, bool encrypted = false);
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
@ -35,9 +39,14 @@ namespace controller {
Poco::AutoPtr<controller::CryptoKey> getCryptoKey() const;
bool hederaAccountGetBalance(Poco::AutoPtr<controller::User> user);
bool hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance);
bool changeEncryption(Poco::AutoPtr<controller::User> user);
//! \brief create Transaction body with this hedera account as operator
std::unique_ptr<model::hedera::TransactionBody> createTransactionBody();
protected:
HederaAccount(model::table::HederaAccount* dbModel);
Poco::AutoPtr<controller::HederaId> mHederaID;

View File

@ -1,4 +1,7 @@
#include "HederaId.h"
#include "../SingletonManager/ErrorManager.h"
using namespace Poco::Data::Keywords;
namespace controller {
@ -30,6 +33,42 @@ namespace controller {
return nullptr;
}
Poco::AutoPtr<HederaId> HederaId::find(int groupId, model::table::HederaNetworkType networkType)
{
auto cm = ConnectionManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
model::table::HederaIdTuple result_tuple;
Poco::Data::Statement select(session);
select << "SELECT h.id, h.shardNum, h.realmNum, h.num FROM hedera_ids as h "
<< "JOIN hedera_topics as topic ON(topic.topic_hedera_id = h.id) "
<< "JOIN hedera_accounts as account ON(account.id = topic.auto_renew_account_hedera_id) "
<< "WHERE topic.group_id = ? AND account.network_type = ?"
, into(result_tuple), use(groupId), use(networkType);
try {
/*select.executeAsync();
select.wait();
auto result_count = select.rowsExtracted();*/
auto result_count = select.execute();
if (1 == result_count) {
return new HederaId(new model::table::HederaId(result_tuple));
}
else {
printf("[HederaId::find] result_count other as expected: %d\n", result_count);
}
}
catch (Poco::Exception& ex) {
auto em = ErrorManager::getInstance();
static const char* function_name = "HederaId::find";
em->addError(new ParamError(function_name, "mysql error: ", ex.displayText()));
em->addError(new ParamError(function_name, "group id: ", groupId));
em->addError(new ParamError(function_name, "network type: ", (int)networkType));
em->sendErrorsAsEmail();
}
return nullptr;
}
void HederaId::copyToProtoAccountId(proto::AccountID* protoAccountId) const
{
auto model = getModel();
@ -38,6 +77,14 @@ namespace controller {
protoAccountId->set_accountnum(model->getNum());
}
void HederaId::copyToProtoTopicId(proto::TopicID* protoTopicId) const
{
auto model = getModel();
protoTopicId->set_shardnum(model->getShardNum());
protoTopicId->set_realmnum(model->getRealmNum());
protoTopicId->set_topicnum(model->getNum());
}
bool HederaId::isExistInDB()
{
auto model = getModel();

View File

@ -2,6 +2,7 @@
#define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE
#include "../model/table/HederaId.h"
#include "../model/table/HederaAccount.h"
#include "Poco/SharedPtr.h"
@ -10,8 +11,10 @@
#include "../proto/hedera/BasicTypes.pb.h"
namespace controller {
class HederaAccount;
class HederaId : public TableControllerBase
{
friend HederaAccount;
public:
~HederaId();
@ -19,6 +22,8 @@ namespace controller {
static Poco::AutoPtr<HederaId> create(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num);
static Poco::AutoPtr<HederaId> load(int id);
//! \return hedera topic id for group and network type (should exist only one)
static Poco::AutoPtr<HederaId> find(int groupId, model::table::HederaNetworkType networkType);
bool isExistInDB();
@ -28,6 +33,7 @@ namespace controller {
inline const model::table::HederaId* getModel() const { return _getModel<model::table::HederaId>(); }
void copyToProtoAccountId(proto::AccountID* protoAccountId) const;
void copyToProtoTopicId(proto::TopicID* protoTopicId) const;
protected:

View File

@ -1,5 +1,6 @@
#include "HederaRequest.h"
#include "../proto/hedera/CryptoService.grpc.pb.h"
#include "../proto/hedera/ConsensusService.grpc.pb.h"
#include "../lib/DataTypeConverter.h"
@ -71,6 +72,33 @@ HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transacti
return HEDERA_REQUEST_RETURN_OK;
}
HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transaction, HederaTask* task)
{
assert(transaction && task);
auto channel = grpc::CreateChannel(transaction->getConnectionString(), grpc::InsecureChannelCredentials());
grpc::ClientContext context;
std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() +
std::chrono::milliseconds(5000);
context.set_deadline(deadline);
auto transaction_type = transaction->getType();
if (model::hedera::TRANSACTION_CONSENSUS_SUBMIT_MESSAGE == transaction_type) {
auto stub = proto::ConsensusService::NewStub(channel);
auto status = stub->submitMessage(&context, *transaction->getTransaction(), task->getTransactionResponse()->getProtoResponse());
if (status.ok()) {
return HEDERA_REQUEST_RETURN_OK;
}
else {
addError(new ParamError("Hedera Request", "consensus service submit message error message:", status.error_message()));
addError(new ParamError("Hedera Request", "details: ", status.error_details()));
return HEDERA_REQUEST_RETURN_ERROR;
}
}
addError(new ParamError("Hedera Request", "not implemnetet or unknown transaction type", transaction_type));
return HEDERA_REQUEST_UNKNOWN_TRANSACTION;
}
#include "Poco/JSON/Object.h"
#include "../lib/JsonRequest.h"

View File

@ -14,12 +14,16 @@
#include "../model/hedera/Query.h"
#include "../model/hedera/Transaction.h"
#include "../model/hedera/Response.h"
#include "../model/hedera/TransactionResponse.h"
#include "../tasks/HederaTask.h"
enum HederaRequestReturn
{
HEDERA_REQUEST_RETURN_OK,
HEDERA_REQUEST_RETURN_PARSE_ERROR,
HEDERA_REQUEST_RETURN_ERROR,
HEDERA_REQUEST_UNKNOWN_TRANSACTION,
HEDERA_REQUEST_UNKNOWN_QUERY,
HEDERA_REQUEST_CONNECT_ERROR
};
@ -32,6 +36,9 @@ public:
HederaRequestReturn request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee = 0);
HederaRequestReturn request(model::hedera::Transaction* transaction, model::hedera::Response* response);
//!
//! \param task goes into HederaTaskManager and will be run after transaction
HederaRequestReturn request(model::hedera::Transaction* transaction, HederaTask* task);
//! for testing, didn't work server say invalid json :/
HederaRequestReturn requestViaPHPRelay(model::hedera::Query* query);

View File

@ -19,6 +19,8 @@ namespace controller {
return Poco::AutoPtr<HederaTopic>(hedera_topic);
}
Poco::UInt64 HederaTopic::hederaCreateTopic()
{
return 0;

View File

@ -13,6 +13,7 @@
#include "TableControllerBase.h"
#include "../model/table/HederaTopic.h"
namespace controller {
class HederaTopic : public TableControllerBase
{
@ -27,6 +28,7 @@ namespace controller {
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
inline Poco::AutoPtr<model::table::HederaTopic> getModel() { return _getModel<model::table::HederaTopic>(); }
@ -36,4 +38,4 @@ namespace controller {
};
}
#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H
#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H

View File

@ -55,6 +55,34 @@ namespace DataTypeConverter
}
}
NumberParseState strToDouble(const std::string& input, double& result)
{
auto comma_position = input.find(',');
std::string input_filtered = input;
if (comma_position > 0 && comma_position != input.npos) {
input_filtered = input_filtered.replace(comma_position, 0, 1, '.');
}
try {
result = stod(input_filtered);
return NUMBER_PARSE_OKAY;
}
catch (const std::invalid_argument& ia)
{
printf("[strToDouble] exception: invalid argument: %s\n", ia.what());
return NUMBER_PARSE_INVALID_ARGUMENT;
}
catch (const std::out_of_range& oor)
{
printf("[strToDouble] exception: out or range: %s\n", oor.what());
return NUMBER_PARSE_OUT_OF_RANGE;
}
catch (const std::logic_error & ler)
{
printf("[strToDouble] exception: logical error: %s\n", ler.what());
return NUMBER_PARSE_LOGIC_ERROR;
}
}
const char* numberParseStateToString(NumberParseState state)
{
switch (state) {

View File

@ -23,6 +23,7 @@ namespace DataTypeConverter {
NumberParseState strToInt(const std::string& input, int& result);
NumberParseState strToInt(const std::string& input, unsigned long long& result);
NumberParseState strToDouble(const std::string& input, double& result);
MemoryBin* hexToBin(const std::string& hexString);
MemoryBin* base64ToBin(const std::string& base64String);

View File

@ -0,0 +1,42 @@
#include "ConsensusSubmitMessage.h"
namespace model {
namespace hedera {
ConsensusSubmitMessage::ConsensusSubmitMessage(Poco::AutoPtr<controller::HederaId> topicID)
: mConsensusMessageBody(nullptr)
{
mConsensusMessageBody = new proto::ConsensusSubmitMessageTransactionBody;
topicID->copyToProtoTopicId(mConsensusMessageBody->mutable_topicid());
}
ConsensusSubmitMessage::~ConsensusSubmitMessage()
{
if (mConsensusMessageBody) {
delete mConsensusMessageBody;
mConsensusMessageBody = nullptr;
}
}
bool ConsensusSubmitMessage::validate()
{
// TODO: unpack gradido transaction and make simple validation check
assert(mConsensusMessageBody);
if (0 == mConsensusMessageBody->message().size()) {
printf("[ConsensusSubmitMessage::validate] empty message\n");
return false;
}
if (!mConsensusMessageBody->has_topicid()) {
printf("[ConsensusSubmitMessage::validate] empty topic id\n");
return false;
}
return true;
}
void ConsensusSubmitMessage::setMessage(std::string byteString)
{
assert(mConsensusMessageBody);
mConsensusMessageBody->set_message(byteString);
}
}
}

View File

@ -0,0 +1,32 @@
#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H
#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H
#include "../../proto/hedera/ConsensusSubmitMessage.pb.h"
#include "../../controller/HederaId.h"
namespace model {
namespace hedera {
class ConsensusSubmitMessage
{
public:
ConsensusSubmitMessage(Poco::AutoPtr<controller::HederaId> topicID);
~ConsensusSubmitMessage();
inline proto::ConsensusSubmitMessageTransactionBody* getProtoTransactionBody() { return mConsensusMessageBody; }
inline void resetPointer() { mConsensusMessageBody = nullptr; }
void setMessage(std::string byteString);
inline void setMessage(const MemoryBin* message) { setMessage(std::string((const char*)message->data(), message->size())); }
bool validate();
protected:
proto::ConsensusSubmitMessageTransactionBody* mConsensusMessageBody;
};
}
}
#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H

View File

@ -3,14 +3,32 @@
namespace model {
namespace hedera {
CryptoCreateTransaction::CryptoCreateTransaction()
CryptoCreateTransaction::CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod)
{
mCryptoCreateBody = new proto::CryptoCreateTransactionBody;
// public key
auto key = mCryptoCreateBody->mutable_key();
auto public_key = new std::string((const char*)publicKey, KeyPairHedera::getPublicKeySize());
key->set_allocated_ed25519(public_key);
mCryptoCreateBody->set_initialbalance(initialBalance);
auto auto_renew_period = mCryptoCreateBody->mutable_autorenewperiod();
auto_renew_period->set_seconds(autoRenewPeriod);
}
CryptoCreateTransaction::~CryptoCreateTransaction()
{
if (mCryptoCreateBody) {
delete mCryptoCreateBody;
mCryptoCreateBody = nullptr;
}
}
bool CryptoCreateTransaction::validate()
{
return true;
}
}
}

View File

@ -3,15 +3,23 @@
#include "../../proto/hedera/CryptoCreate.pb.h"
#include "../Crypto/KeyPairHedera.h"
namespace model {
namespace hedera {
class CryptoCreateTransaction
{
public:
CryptoCreateTransaction();
//! \param publicKey newly created public key from ed25519 public-private key pair for hedera
CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod);
~CryptoCreateTransaction();
proto::CryptoCreateTransactionBody* getProtoTransactionBody() { return mCryptoCreateBody; }
inline void resetPointer() { mCryptoCreateBody = nullptr; }
bool validate();
protected:
proto::CryptoCreateTransactionBody* mCryptoCreateBody;
};

View File

@ -43,11 +43,6 @@ namespace model {
}
return 0 == sum && transfers->accountamounts_size() > 0;
}
void CryptoTransferTransaction::resetPointer()
{
mCryptoTransfer = nullptr;
}
}
}

View File

@ -26,7 +26,7 @@ namespace model {
bool validate();
// set pointer to zero, after hand over pointer to transaction body
void resetPointer();
inline void resetPointer() { mCryptoTransfer = nullptr; }
inline proto::CryptoTransferTransactionBody* getProtoTransactionBody() { return mCryptoTransfer; }

View File

@ -18,6 +18,8 @@ namespace model {
bool Transaction::sign(std::unique_ptr<KeyPairHedera> keyPairHedera, const TransactionBody* transactionBody)
{
mType = transactionBody->getType();
auto mm = MemoryManager::getInstance();
mConnection = transactionBody->getConnection();
auto transaction_body_proto = transactionBody->getProtoTransactionBody();
@ -40,5 +42,32 @@ namespace model {
mm->releaseMemory(sign);
return true;
}
bool Transaction::sign(std::unique_ptr<KeyPairHedera> keyPairHedera, std::unique_ptr<TransactionBody> transactionBody)
{
mType = transactionBody->getType();
auto mm = MemoryManager::getInstance();
mConnection = transactionBody->getConnection();
auto transaction_body_proto = transactionBody->getProtoTransactionBody();
auto body_bytes = transaction_body_proto->SerializeAsString();
mTransaction->set_bodybytes(body_bytes.data(), body_bytes.size());
auto signature_map = mTransaction->mutable_sigmap();
auto signature_pairs = signature_map->mutable_sigpair();
signature_map->add_sigpair();
auto signature_pair = signature_pairs->Mutable(0);
auto public_key = keyPairHedera->getPublicKey();
auto sign = keyPairHedera->sign(body_bytes);
if (!sign) {
printf("[Query::sign] error signing message\n");
return false;
}
signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize());
signature_pair->set_ed25519(*sign, sign->size());
mm->releaseMemory(sign);
return true;
}
}
}

View File

@ -23,14 +23,17 @@ namespace model {
~Transaction();
bool sign(std::unique_ptr<KeyPairHedera> keyPairHedera, const TransactionBody* transactionBody);
bool sign(std::unique_ptr<KeyPairHedera> keyPairHedera, std::unique_ptr<TransactionBody> transactionBody);
inline proto::Transaction* getTransaction() { return mTransaction; }
inline std::string getConnectionString() const { return mConnection.getUriWithPort(); }
void resetPointer() { mTransaction = nullptr; }
inline TransactionBodyType getType() const { return mType; }
protected:
proto::Transaction* mTransaction;
controller::NodeServerConnection mConnection;
TransactionBodyType mType;
};
}
}

View File

@ -3,7 +3,7 @@
namespace model {
namespace hedera {
TransactionBody::TransactionBody(Poco::AutoPtr<controller::HederaId> operatorAccountId, const controller::NodeServerConnection& connection)
: mConnection(connection)
: mConnection(connection), mHasBody(false)
{
connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid());
auto transaction_id = mTransactionBody.mutable_transactionid();
@ -22,9 +22,15 @@ namespace model {
bool TransactionBody::setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction)
{
if (mHasBody) {
printf("[TransactionBody::setCryptoTransfer] has already a body\n");
return false;
}
if (cryptoTransferTransaction.validate()) {
mTransactionBody.set_allocated_cryptotransfer(cryptoTransferTransaction.getProtoTransactionBody());
cryptoTransferTransaction.resetPointer();
mHasBody = true;
mType = TRANSACTION_CRYPTO_TRANSFER;
return true;
}
return false;
@ -32,9 +38,47 @@ namespace model {
bool TransactionBody::setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction)
{
if (mHasBody) {
printf("[TransactionBody::setCreateTopic] has already a body\n");
return false;
}
if (consensusCreateTopicTransaction.validate()) {
mTransactionBody.set_allocated_consensuscreatetopic(consensusCreateTopicTransaction.getProtoTransactionBody());
consensusCreateTopicTransaction.resetPointer();
mHasBody = true;
mType = TRANSACTION_CONSENSUS_CREATE_TOPIC;
return true;
}
return false;
}
bool TransactionBody::setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction)
{
if (mHasBody) {
printf("[TransactionBody::setCryptoCreate] has already a body\n");
return false;
}
if (cryptoCreateTransaction.validate()) {
mTransactionBody.set_allocated_cryptocreateaccount(cryptoCreateTransaction.getProtoTransactionBody());
cryptoCreateTransaction.resetPointer();
mHasBody = true;
mType = TRANSACTION_CRYPTO_CREATE;
return true;
}
return false;
}
bool TransactionBody::setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction)
{
if (mHasBody) {
printf("[TransactionBody::setConsensusSubmitMessage] has already a body\n");
return false;
}
if (consensusSubmitMessageTransaction.validate()) {
mTransactionBody.set_allocated_consensussubmitmessage(consensusSubmitMessageTransaction.getProtoTransactionBody());
consensusSubmitMessageTransaction.resetPointer();
mHasBody = true;
mType = TRANSACTION_CONSENSUS_SUBMIT_MESSAGE;
return true;
}
return false;

View File

@ -13,12 +13,23 @@
#include "../../controller/NodeServer.h"
#include "CryptoTransferTransaction.h"
#include "CryptoCreateTransaction.h"
#include "ConsensusCreateTopic.h"
#include "ConsensusSubmitMessage.h"
#include "../../proto/hedera/TransactionBody.pb.h"
namespace model {
namespace hedera {
enum TransactionBodyType
{
TRANSACTION_CRYPTO_TRANSFER,
TRANSACTION_CRYPTO_CREATE,
TRANSACTION_CONSENSUS_CREATE_TOPIC,
TRANSACTION_CONSENSUS_SUBMIT_MESSAGE
};
class TransactionBody
{
public:
@ -29,17 +40,22 @@ namespace model {
void setFee(Poco::UInt64 fee);
bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction);
bool setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction);
bool setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction);
bool setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction);
//bool
inline const proto::TransactionBody* getProtoTransactionBody() const { return &mTransactionBody; }
inline std::string getConnectionString() const { return mConnection.getUriWithPort(); }
inline controller::NodeServerConnection getConnection() const { return mConnection; }
inline TransactionBodyType getType() const { return mType; }
protected:
void updateTimestamp();
proto::TransactionBody mTransactionBody;
controller::NodeServerConnection mConnection;
bool mHasBody;
TransactionBodyType mType;
};
}
}

View File

@ -0,0 +1,18 @@
#include "TransactionResponse.h"
namespace model {
namespace hedera {
TransactionResponse::TransactionResponse()
{
}
TransactionResponse::~TransactionResponse()
{
}
}
}

View File

@ -0,0 +1,30 @@
#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H
#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H
#include "../../proto/hedera/TransactionResponse.pb.h"
#include "Poco/Types.h"
namespace model {
namespace hedera {
class TransactionResponse
{
public:
TransactionResponse();
~TransactionResponse();
inline proto::ResponseCodeEnum getPrecheckCode() const { return mProtoResponse.nodetransactionprecheckcode();}
inline std::string getPrecheckCodeString() const { return proto::ResponseCodeEnum_Name(mProtoResponse.nodetransactionprecheckcode()); }
inline Poco::UInt64 getCost() const { return mProtoResponse.cost(); }
proto::TransactionResponse* getProtoResponse() { return &mProtoResponse; }
protected:
proto::TransactionResponse mProtoResponse;
};
}
}
#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H

View File

@ -16,6 +16,13 @@ namespace model {
}
HederaId::HederaId(const HederaIdTuple& tuple)
: ModelBase(tuple.get<0>()),
mShardNum(tuple.get<1>()), mRealmNum(tuple.get<2>()), mNum(tuple.get<3>())
{
}
HederaId::~HederaId()
{

View File

@ -7,11 +7,14 @@
namespace model {
namespace table {
typedef Poco::Tuple<int, Poco::UInt64, Poco::UInt64, Poco::UInt64> HederaIdTuple;
class HederaId : public ModelBase
{
public:
HederaId();
HederaId(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num);
HederaId(const HederaIdTuple& tuple);
~HederaId();
// generic db operations
@ -25,7 +28,6 @@ namespace model {
inline Poco::UInt64 getRealmNum() const { return mRealmNum; }
inline Poco::UInt64 getNum() const { return mNum; }
protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session);

View File

View File

@ -0,0 +1,15 @@
#ifndef __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H
#define __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H
#include "../model/hedera/TransactionResponse.h"
class HederaTask
{
public:
inline model::hedera::TransactionResponse* getTransactionResponse() { return &mTransactionResponse; }
protected:
model::hedera::TransactionResponse mTransactionResponse;
};
#endif //__GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H

View File

@ -20,6 +20,12 @@
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
// stuff for hedera transaction
#include "../controller/HederaAccount.h"
#include "../controller/HederaRequest.h"
#include "../model/hedera/TransactionBody.h"
#include "../model/hedera/Transaction.h"
SigningTransaction::SigningTransaction(Poco::AutoPtr<ProcessingTransaction> processingeTransaction, Poco::AutoPtr<controller::User> newUser)
: mProcessingeTransaction(processingeTransaction), mNewUser(newUser)
{
@ -152,6 +158,41 @@ int SigningTransaction::run() {
return -6;
}
auto network_type = model::table::HEDERA_TESTNET;
auto topic_id = controller::HederaId::find(1, network_type);
auto hedera_operator_account = controller::HederaAccount::pick(network_type, false);
if (!topic_id.isNull() && !hedera_operator_account.isNull()) {
auto crypto_key = hedera_operator_account->getCryptoKey();
if (!crypto_key.isNull()) {
model::hedera::ConsensusSubmitMessage consensus_submit_message(topic_id);
consensus_submit_message.setMessage(finalTransactionBin);
auto hedera_transaction_body = hedera_operator_account->createTransactionBody();
hedera_transaction_body->setConsensusSubmitMessage(consensus_submit_message);
model::hedera::Transaction hedera_transaction;
hedera_transaction.sign(crypto_key->getKeyPair(), std::move(hedera_transaction_body));
HederaRequest hedera_request;
HederaTask hedera_task;// placeholder
if (HEDERA_REQUEST_RETURN_OK != hedera_request.request(&hedera_transaction, &hedera_task)) {
addError(new Error("SigningTransaction", "error send transaction to hedera"));
getErrors(&hedera_request);
sendErrorsAsEmail();
}
else {
auto hedera_precheck_code_string = hedera_task.getTransactionResponse()->getPrecheckCodeString();
printf("hedera response: %s\n", hedera_precheck_code_string.data());
}
//model::hedera::TransactionBody hedera_transaction_body()
}
else {
printf("[SigningTransaction] crypto key not found\n");
}
}
else {
printf("[SigningTransaction] hedera topic id or operator account not found\n");
}
// finale to base64
auto finalBase64Size = sodium_base64_encoded_len(finalTransactionBin.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING);
auto finalBase64Bin = mm->getFreeMemory(finalBase64Size);

View File

@ -24,6 +24,9 @@
auto sm = SessionManager::getInstance();
auto mm = MemoryManager::getInstance();
auto user = mSession->getNewUser();
int auto_renew_period = 604800; // 7 Tage
int auto_renew_account = 0;
double initial_balance = 0.0;
Profiler hedera_time;
std::string hedera_time_string;
@ -59,8 +62,11 @@
if(action == "updateBalance")
{
hedera_time.reset();
query_hedera_account->hederaAccountGetBalance(user);
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
if(query_hedera_account->hederaAccountGetBalance(user)) {
addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string()));
} else {
addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string()));
}
}
else if(action == "changeEncryption")
{
@ -69,113 +75,150 @@
}
}
}
else if(!form.empty()) // add
else if(!form.empty()) // add or create
{
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
auto creationButton = form.get("create","");
if(creationButton != "") {
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
int networkType = 0;
MemoryBin* private_key = nullptr;
MemoryBin* public_key = nullptr;
// validate
if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "shard num not integer"));
} else {
if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting shardNumString to int"));
}
}
if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "realm num not integer"));
} else {
if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting realmNumString to int"));
}
}
if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "num not integer"));
} else {
if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting num to int"));
}
}
if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "private key not hex"));
}
if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "public key not hex"));
}
if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Network Type", "not integer"));
} else {
if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting network type to int"));
}
if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) {
addError(new Error("Network Type", "invalid value"));
}
}
if(0 == errorCount()) {
auto hedera_id = controller::HederaId::create(shardNum, realmNum, num);
// collect
auto auto_renew_account_string = form.get("account-auto-renew-account", "0");
auto auto_renew_period_string = form.get("account-auto-renew-period", "604800");
auto account_initial_balance_string = form.get("account-initial-balance", "0");
private_key = DataTypeConverter::hexToBin(privateKeyString);
public_key = DataTypeConverter::hexToBin(publicKeyString);
KeyPairHedera key_pair(private_key, public_key);
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account", "auto renew account id not an integer"));
} else {
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int convert error", "Error converting auto renew account id to int"));
}
}
mm->releaseMemory(private_key);
mm->releaseMemory(public_key);
}
if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account", "auto renew period not an integer"));
} else {
if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int convert error", "Error converting auto renew period to int"));
}
}
if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) {
addError(new Error("Account", "initial balance not an decimal"));
} else {
if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Double convert error", "Error converting initial balance to double"));
}
}
if(0 == errorCount())
{
}
} else {
// collect
auto shardNumString = form.get("account-shard-num", "0");
auto realmNumString = form.get("account-realm-num", "0");
auto numString = form.get("account-num", "0");
auto privateKeyString = form.get("account-private-key", "");
auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false");
auto publicKeyString = form.get("account-public-key", "");
auto networkTypeString = form.get("account-network-type", "0");
//printf("private key encrypted: %s\n", privateKeyEncryptedString.data());
int shardNum = 0;
int realmNum = 0;
int num = 0;
int networkType = 0;
MemoryBin* private_key = nullptr;
MemoryBin* public_key = nullptr;
// validate
if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "shard num not integer"));
} else {
if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting shardNumString to int"));
}
}
if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "realm num not integer"));
} else {
if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting realmNumString to int"));
}
}
if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Account ID", "num not integer"));
} else {
if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting num to int"));
}
}
if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "private key not hex"));
}
if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) {
addError(new Error("Account Keys", "public key not hex"));
}
if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) {
addError(new Error("Network Type", "not integer"));
} else {
if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) {
addError(new Error("Int Convert Error", "Error converting network type to int"));
}
if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) {
addError(new Error("Network Type", "invalid value"));
}
}
if(0 == errorCount()) {
auto hedera_id = controller::HederaId::create(shardNum, realmNum, num);
private_key = DataTypeConverter::hexToBin(privateKeyString);
public_key = DataTypeConverter::hexToBin(publicKeyString);
KeyPairHedera key_pair(private_key, public_key);
auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE);
if(crypto_key.isNull()) {
crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true");
if(!crypto_key->getModel()->insertIntoDB(true)) {
addError(new Error("DB Error", "Error saving crypto key in DB"));
}
} else {
printf("crypto key found in db\n");
}
if(0 == errorCount()) {
if(hedera_id->isExistInDB()) {
auto hedera_account = controller::HederaAccount::load(hedera_id);
if(hedera_account.isNull()) {
addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist"));
} else {
addError(new Error("Hedera Account", "Account already exist (same account id"));
}
} else {
auto hedera_account = controller::HederaAccount::create(
user->getModel()->getID(),
hedera_id->getModel()->getID(),
crypto_key->getModel()->getID(),
0,
(model::table::HederaNetworkType)networkType
);
if(!hedera_account->getModel()->insertIntoDB(false)) {
addError(new Error("DB Error", "Error saving hedera account into DB"));
}
}
}
mm->releaseMemory(private_key);
mm->releaseMemory(public_key);
}
}
}
if(!query_hedera_account.isNull()) {
getErrors(query_hedera_account);
@ -184,6 +227,14 @@
auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID());
%><%@ include file="header_large.cpsp" %>
<style type="text/css">
.center-form-form .input-40 {
margin-left:0;
width:40%;
display:inline-block;
}
</style>
<%= getErrorsHtml() %>
<div class="center-form-container">
@ -207,13 +258,14 @@
if(hedera_account_model->getUserId() == user->getModel()->getID()) {
changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID());
}
auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted();
//printf("change encryption: %s\n", changeEncryption.data());
%>
<div class="row">
<div class="cell c2"><%= (*it)->getHederaId()->getModel()->toString() %></div>
<div class="cell c3"><%= hedera_account_model->getBalanceDouble() %> hbar</div>
<div class="cell c2"><%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %></div>
<div class="cell c3"><%= (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" %></div>
<div class="cell c3 <%= isEncrypted ? "success-color" : "alert-color"%>"><%= isEncrypted ? "Ja": "Nein" %></div>
<div class="cell c3"><%= hedera_account_model->getUpdatedString() %></div>
<button class="form-button" title="Anfrage an Hedera, aktuell kostenlos" onclick="window.location.href='<%= updateUrl %>'" >
Update Balance
@ -228,7 +280,7 @@
</div>
</div>
<div class="center-form-title">
<h3>Einen neuen Account anlegen</h3>
<h3>Ein existierenden Account eintragen</h3>
</div>
<div class="center-form-form">
<form method="POST" action="<%= ServerConfig::g_serverPath %>/hedera_account">
@ -248,8 +300,39 @@
<option value="<%= i %>"><%= model::table::HederaAccount::hederaNetworkTypeToString((model::table::HederaNetworkType)i) %></option>
<% } %>
</select>
<input class="center-form-submit form-button" type="submit" name="submit" value="<%= gettext("Add Account") %>">
<input class="center-form-submit form-button" type="submit" name="add" value="<%= gettext("Add Account") %>">
</form>
</div>
<div class="center-form-title">
<h3>Ein neuen Account anlegen</h3>
<p>Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.</p>
</div>
<div class="center-form-form">
<form method="POST" action="<%= ServerConfig::g_serverPath %>/hedera_account">
<label class="form-label" for="account-auto-renew-account">Auto Renew and Founding Hedera Account</label>
<select name="account-auto-renew-account" id="account-auto-renew-account">
<% for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) {
auto model = (*it)->getModel();
%>
<option title="<%= model->toString() %>" value="<%= model->getID() %>" <% if(auto_renew_account == model->getID()) {%>selected="selected"<% } %>><%= (*it)->toShortSelectOptionName() %></option>
<% } %>
</select>
<label class="form-label" for="account-auto-renew-period">Auto Renew Period in seconds</label>
<div><input class="form-control input-40" id="account-auto-renew-period" value="<%= auto_renew_period %>" type="number" name="account-auto-renew-period"/><span style="margin-left:8px" id="readable-auto-renew-period"></span><div>
<label class="form-label" for="account-initial-balance">Initial Balance for new Account (taken from founding account)</label>
<input class="form-control" id="account-initial-balance" name="account-initial-balance" type="number" step="0.00000001" value="<%= std::to_string(initial_balance) %>" />
<input class="center-form-submit form-button" type="submit" name="create" value="<%= gettext("Create Account") %>">
</form>
</div>
</div>
<%@ include file="footer.cpsp" %>
<script type="text/javascript" src="<%= ServerConfig::g_php_serverPath %>/js/time_calculations.js"></script>
<script type="text/javascript">
var input = document.getElementById("account-auto-renew-period");
var span = document.getElementById("readable-auto-renew-period");
span.innerHTML = '~ ' + getExactTimeDuration(input.value);
input.addEventListener('keyup', function(e) {
span.innerHTML = '~ ' + getExactTimeDuration(input.value);
});
</script>