mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Update code for sending transaction over hedera
This commit is contained in:
parent
eaf95f87e4
commit
7449f73e89
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
17
src/cpp/SingletonManager/HederaTaskManager.cpp
Normal file
17
src/cpp/SingletonManager/HederaTaskManager.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "HederaTaskManager.h"
|
||||
|
||||
HederaTaskManager* HederaTaskManager::getInstance()
|
||||
{
|
||||
static HederaTaskManager one;
|
||||
return &one;
|
||||
}
|
||||
|
||||
HederaTaskManager::HederaTaskManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HederaTaskManager::~HederaTaskManager()
|
||||
{
|
||||
|
||||
}
|
||||
23
src/cpp/SingletonManager/HederaTaskManager.h
Normal file
23
src/cpp/SingletonManager/HederaTaskManager.h
Normal 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
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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()
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ namespace controller {
|
||||
return Poco::AutoPtr<HederaTopic>(hedera_topic);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Poco::UInt64 HederaTopic::hederaCreateTopic()
|
||||
{
|
||||
return 0;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -43,11 +43,6 @@ namespace model {
|
||||
}
|
||||
return 0 == sum && transfers->accountamounts_size() > 0;
|
||||
}
|
||||
|
||||
void CryptoTransferTransaction::resetPointer()
|
||||
{
|
||||
mCryptoTransfer = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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; }
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
18
src/cpp/model/hedera/TransactionResponse.cpp
Normal file
18
src/cpp/model/hedera/TransactionResponse.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "TransactionResponse.h"
|
||||
|
||||
namespace model {
|
||||
namespace hedera {
|
||||
|
||||
TransactionResponse::TransactionResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TransactionResponse::~TransactionResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
30
src/cpp/model/hedera/TransactionResponse.h
Normal file
30
src/cpp/model/hedera/TransactionResponse.h
Normal 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
|
||||
@ -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()
|
||||
{
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
0
src/cpp/tasks/HederaTask.cpp
Normal file
0
src/cpp/tasks/HederaTask.cpp
Normal file
15
src/cpp/tasks/HederaTask.h
Normal file
15
src/cpp/tasks/HederaTask.h
Normal 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
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user