Newer
Older
dap_chain_node_client_close(client);
DAP_DELETE(node_info);
return -1;
}
// send request
size_t l_data_size_out = 0;
// Get last timestamp in log
time_t l_timestamp_start = dap_db_log_get_last_timestamp();
size_t l_data_send_len = 0;
uint8_t *l_data_send = dap_stream_ch_chain_net_make_packet(l_cur_node_addr, node_info->hdr.address.uint64,
l_timestamp_start, NULL, 0, &l_data_send_len);
uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for global_db sync
res = dap_chain_node_client_send_chain_net_request(client, l_ch_id,
STREAM_CH_CHAIN_NET_PKT_TYPE_GLOBAL_DB_REQUEST_SYNC, l_data_send, l_data_send_len); //, NULL);
DAP_DELETE(l_data_send);
set_reply_text(str_reply, "no request sent");
// clean client struct
dap_chain_node_client_close(client);
DAP_DELETE(node_info);
return -1;
}
// wait for finishing of request
timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms
// TODO add progress info to console
res = chain_node_client_wait(client, NODE_CLIENT_STATE_END, timeout_ms);
DAP_DELETE(node_info);
dap_client_disconnect(client->client);
dap_chain_node_client_close(client);
switch (res) {
case 0:
set_reply_text(str_reply, "timeout");
return -1;
case 1:
set_reply_text(str_reply, "nodes sync completed");
return 0;
default:
set_reply_text(str_reply, "error");
return -1;
}
// get address from alias if addr not defined
if(alias_str && !address.uint64) {
dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
if(address_tmp) {
memcpy(&address, address_tmp, sizeof(address_tmp));
DAP_DELETE(address_tmp);
}
else {
set_reply_text(str_reply, "no address found by alias");
return -1;
}
}
if(!address.uint64) {
set_reply_text(str_reply, "addr not found");
return -1;
}
dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
int timeout_ms = 10000; //10 sec = 10000 ms
dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
if(!client) {
set_reply_text(str_reply, "can't connect");
DAP_DELETE(node_info);
return -1;
}
// wait handshake
int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
if(res != 1) {
set_reply_text(str_reply, "no response from node");
// clean client struct
DAP_DELETE(node_info);
return -1;
}
DAP_DELETE(node_info);
//Add new established connection in the list
int ret = chain_node_client_list_add(&address, client);
switch (ret)
{
case -1:
dap_chain_node_client_close(client);
set_reply_text(str_reply, "connection established, but not saved");
return -1;
case -2:
dap_chain_node_client_close(client);
set_reply_text(str_reply, "connection already present");
return -1;
}
set_reply_text(str_reply, "connection established");
return 0;
}
/**
* Traceroute command
*
* return 0 OK, -1 Err
*/
int com_traceroute(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? traceroute_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
set_reply_text(str_reply, "traceroute %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
set_reply_text(str_reply, "traceroute %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case 2:
set_reply_text(str_reply, "traceroute %s error: %s", addr, "Unknown traceroute module");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "first hop out of range");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "max hops cannot be more than 255");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "no more than 10 probes per hop");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad wait specifications");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "too big packetlen ");
set_reply_text(str_reply, "traceroute %s error: %s", addr,
"IP version mismatch in addresses specified");
break;
case 9:
set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad sendtime");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "init_ip_options");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "calloc");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "parse cmdline");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "trace method's init failed");
set_reply_text(str_reply, "traceroute %s error(%d) %s", addr, res, "trace not found");
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
}
}
}
return res;
}
/**
* Tracepath command
*
* return 0 OK, -1 Err
*/
int com_tracepath(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? tracepath_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
set_reply_text(str_reply, "tracepath %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
set_reply_text(str_reply, "tracepath %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case ESOCKTNOSUPPORT:
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't create socket");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_MTU_DISCOVER");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_MTU_DISCOVER");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "malloc");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_UNICAST_HOPS");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_TTL");
set_reply_text(str_reply, "tracepath %s error(%d) %s", addr, res, "trace not found");
}
}
}
return res;
}
/**
* Ping command
*
* return 0 OK, -1 Err
*/
int com_ping(int argc, const char** argv, char **str_reply)
{
int n = 4;
if(argc < 2) {
set_reply_text(str_reply, "host not specified");
return -1;
}
int argc_host = 1;
int argc_start = 1;
argc_start = find_option_val(argv, argc_start, argc, "-n", &n_str);
if(argc_start) {
argc_host = argc_start + 1;
}
else {
argc_start = find_option_val(argv, argc_start, argc, "-c", &n_str);
if(argc_start) {
argc_host = argc_start + 1;
n = (n_str) ? atoi(n_str) : 4;
}
}
const char *addr = argv[argc_host];
iputils_set_verbose();
int res = (addr) ? ping_util(addr, n) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
set_reply_text(str_reply, "ping %s time=%.1lf ms", addr, res * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EDESTADDRREQ:
set_reply_text(str_reply, "ping %s error: %s", addr, "Destination address required");
set_reply_text(str_reply, "ping %s error: %s", (addr) ? addr : "",
(addr) ? "Host not found" : "Host not defined");
break;
case EPFNOSUPPORT:
set_reply_text(str_reply, "ping %s error: %s", addr, "Unknown protocol family");
set_reply_text(str_reply, "ping %s error(%d)", addr, -res);
}
}
}
return res;
}
/**
* Help command
*/
int com_help(int argc, const char ** argv, char **str_reply)
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
{
if(argc > 1) {
const COMMAND *cmd = find_command(argv[1]);
if(cmd)
{
set_reply_text(str_reply, "%s:\n%s", cmd->doc, cmd->doc_ex);
return 1;
}
set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]);
return -1;
}
else {
// TODO Read list of commands & return it
}
if(str_reply)
set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\"");
return -1;
}
/**
* com_tx_create command
*
* Wallet info
*/
int com_tx_wallet(int argc, const char ** argv, char **str_reply)
{
const char *c_wallets_path = dap_config_get_item_str(g_config, "general", "wallets_path");
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
// Get address of wallet
enum {
CMD_NONE, CMD_WALLET_LIST, CMD_WALLET_INFO
};
int arg_index = 1;
int cmd_num = CMD_NONE;
const char *cmd_str = NULL;
// find add parameter ('alias' or 'handshake')
if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "list", NULL)) {
cmd_num = CMD_WALLET_LIST;
}
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "info", NULL)) {
cmd_num = CMD_WALLET_INFO;
}
arg_index++;
if(cmd_num == CMD_NONE) {
set_reply_text(str_reply, "format of command: wallet [list | info -addr <addr> -w <wallet_name>]");
return -1;
}
dap_chain_node_addr_t address;
memset(&address, 0, sizeof(dap_chain_node_addr_t));
const char *addr_str = NULL, *wallet_name = NULL;
// find wallet addr
find_option_val(argv, arg_index, argc, "-addr", &addr_str);
find_option_val(argv, arg_index, argc, "-w", &wallet_name);
dap_string_t *l_string_ret = dap_string_new(NULL);
switch (cmd_num) {
// wallet list
case CMD_WALLET_LIST: {
GDir *l_dir = g_dir_open(c_wallets_path, 0, NULL);
if(l_dir) {
const char *l_file = NULL;
do {
l_file = g_dir_read_name(l_dir);
int l_file_len = (l_file) ? strlen(l_file) : 0;
if(l_file_len > 8 && !g_strcmp0(l_file + l_file_len - 8, ".dwallet")) {
char *l_file_path_tmp = dap_strdup_printf("%s/%s", c_wallets_path, l_file);
dap_chain_wallet_t *l_wallet = dap_chain_wallet_open_file(l_file_path_tmp);
if(l_wallet) {
dap_chain_addr_t *l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
dap_string_append_printf(l_string_ret, "\nwallet: %s\n", l_wallet->name);
dap_string_append_printf(l_string_ret, "addr: %s\n", (l_addr_str) ? l_addr_str : "-");
DAP_DELETE(l_addr_str);
dap_chain_wallet_close(l_wallet);
}
}
}
while(l_file);
g_dir_close(l_dir);
}
}
break;
// wallet info
case CMD_WALLET_INFO: {
dap_chain_wallet_t *l_wallet = NULL;
dap_chain_addr_t *l_addr = NULL;
if(wallet_name) {
l_wallet = dap_chain_wallet_open(wallet_name, c_wallets_path);
l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
}
if(!l_addr && addr_str)
l_addr = dap_chain_str_to_addr(addr_str);
if(l_addr) {
char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
if(l_wallet)
dap_string_append_printf(l_string_ret, "\nwallet: %s\n", l_wallet->name);
dap_string_append_printf(l_string_ret, "addr: %s\n", (l_addr_str) ? l_addr_str : "-");
size_t l_addr_tokens_size = 0;
char **l_addr_tokens = NULL;
dap_chain_utxo_addr_get_token_ticker_all(l_addr, &l_addr_tokens, &l_addr_tokens_size);
if(l_addr_tokens_size>0)
dap_string_append_printf(l_string_ret, "balance:\n");
else
dap_string_append_printf(l_string_ret, "balance: 0\n");
for(size_t i = 0; i < l_addr_tokens_size; i++) {
if(l_addr_tokens[i]) {
uint64_t balance = dap_chain_utxo_calc_balance(l_addr, l_addr_tokens[i]);
dap_string_append_printf(l_string_ret, " %llu %s\n", balance, l_addr_tokens[i]);
if(l_wallet)
dap_chain_wallet_close(l_wallet);
if(l_wallet)
dap_chain_wallet_close(l_wallet);
dap_string_free(l_string_ret, true);
set_reply_text(str_reply, "wallet not found");
return -1;
}
}
break;
}
char *l_str_ret_tmp = dap_string_free(l_string_ret, false);
char *str_ret = dap_strdup(l_str_ret_tmp);
set_reply_text(str_reply, str_ret);
/**
* @brief com_token_emit
* @param argc
* @param argv
* @param str_reply
* @return
*/
int com_token_emit(int argc, const char ** argv, char ** str_reply)
{
int arg_index = 1;
const char *str_tmp = NULL;
uint64_t l_emission_value = 0;
const char * l_ticker = NULL;
const char * l_addr_str = NULL;
const char * l_certs_str = NULL;
dap_chain_cert_t ** l_certs = NULL;
size_t l_certs_size = 0;
// Wallet address that recieves the emission
find_option_val(argv, arg_index, argc, "certs", &l_certs_str);
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
// Wallet address that recieves the emission
find_option_val(argv, arg_index, argc, "addr", &l_addr_str);
// Token ticker
find_option_val(argv, arg_index, argc, "token", &l_ticker);
// Token emission
if(find_option_val(argv, arg_index, argc, "emission_value", &str_tmp)) {
l_emission_value = strtoull(str_tmp, NULL, 10);
}
if(!l_emission_value) {
set_reply_text(str_reply, "token_emit requires parameter 'emission_value'");
return -1;
}
if(!l_addr_str) {
set_reply_text(str_reply, "token_emit requires parameter 'addr'");
return -2;
}
if(!l_ticker) {
set_reply_text(str_reply, "token_emit requires parameter 'tokent'");
return -3;
}
set_reply_text(str_reply, "token_emit requires parameter 'certs'");
return -4;
}
int n = 0;
char * l_certs_str_dup = strdup(l_certs_str);
char *l_cert_str = strtok_r(l_certs_str_dup, ",", &l_certs_tmp_ptrs);
//debug
{
const char * l_wallets_path = dap_config_get_item_str(g_config, "general", "wallets_path");
dap_chain_net_id_t a_net_id;
a_net_id.uint64 = 0x123;
dap_chain_sign_type_t l_type;
l_type.type = 0x0003;// SIG_TYPE_TESLA=0x0003
dap_chain_wallet_t *wallet1 = dap_chain_wallet_create("tesla_first", l_wallets_path, a_net_id, l_type);
dap_chain_wallet_t *wallet2 = dap_chain_wallet_create("tesla_second", l_wallets_path, a_net_id, l_type);
wallet1 = NULL;
}
// First we just calc items
while(l_cert_str) {
l_cert_str = strtok_r(NULL, ",", &l_certs_tmp_ptrs);
l_certs_size++;
}
// init certs array
l_certs = DAP_NEW_Z_SIZE(dap_chain_cert_t*, l_certs_size);
// Second pass we parse them all
strcpy(l_certs_str_dup, l_certs_str);
l_cert_str = strtok_r(l_certs_str_dup, ",", &l_certs_tmp_ptrs);
while(l_cert_str) {
// trim token whitespace
if(isspace(l_cert_str[strlen(l_cert_str) - 1]))
l_cert_str[strlen(l_cert_str) - 1] = 0;
l_certs[l_certs_pos] = dap_chain_cert_find_by_name(l_cert_str);
l_certs_pos++;
} else {
set_reply_text(str_reply, "Error: can't find %s certificate", l_cert_str);
return -6;
}
l_cert_str = strtok_r(NULL, ",", &l_certs_tmp_ptrs);
if(!l_certs_size) {
set_reply_text(str_reply,
"token_emit command requres at least one valid certificate to sign the basic transaction of emission");
return -5;
}
dap_chain_addr_t * l_addr = dap_chain_str_to_addr(l_addr_str);
if(!l_addr) {
set_reply_text(str_reply, "address \"%s\" is invalid", l_addr_str);
return -4;
}
// Create emission datum
dap_chain_datum_token_emission_t * l_token_emission;
dap_chain_hash_fast_t l_token_emission_hash;
l_token_emission = DAP_NEW_Z(dap_chain_datum_token_emission_t);
strncpy(l_token_emission->ticker, l_ticker, sizeof(l_token_emission->ticker));
l_token_emission->value = l_emission_value;
dap_hash_fast(l_token_emission, sizeof(dap_chain_datum_token_emission_t), &l_token_emission_hash);
dap_chain_datum_t * l_datum_emission = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_EMISSION,
l_token_emission,
sizeof(dap_chain_datum_token_emission_t));
size_t l_datum_emission_size = sizeof(l_datum_emission->header) + l_datum_emission->header.data_size;
dap_hash_fast(l_datum_emission, l_datum_emission_size, &l_key_hash);
char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
// Add to mempool emission token
if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_emission, l_datum_emission_size
, dap_config_get_item_str_default(g_config, "mempool", "gdb_group", "datum-pool"))) {
str_reply_tmp = dap_strdup_printf("datum emission %s is placed in datum pool ", l_key_str);
else{
set_reply_text(str_reply, "datum emission %s is not placed in datum pool ", l_key_str);
return -1;
}
DAP_DELETE(l_key_str);
// create first transaction (with tx_token)
dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
dap_chain_hash_fast_t l_tx_prev_hash = { 0 };
dap_chain_hash_fast_t l_datum_token_hash = { 0 };
// create items
dap_chain_tx_token_t *l_tx_token = dap_chain_datum_tx_item_token_create(&l_token_emission_hash, l_ticker);
dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, 0);
dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(l_addr, l_emission_value);
// pack items to transaction
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_tx_token);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_out);
// Sign all that we have with certs
for(size_t i = 0; i < l_certs_size; i++)
dap_chain_datum_tx_add_sign_item(&l_tx, l_certs[i]->enc_key);
DAP_DELETE(l_certs);
DAP_DELETE(l_tx_token);
DAP_DELETE(l_in);
DAP_DELETE(l_out);
size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
// Pack transaction into the datum
dap_chain_datum_t * l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size);
size_t l_datum_tx_size = dap_chain_datum_data_size(l_datum_tx);
// use l_tx hash for compatible with utho hash
dap_hash_fast(l_tx, l_tx_size, &l_key_hash);//dap_hash_fast(l_datum_tx, l_datum_tx_size, &l_key_hash);
l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_tx, l_datum_tx_size
, dap_config_get_item_str_default(g_config, "mempool", "gdb_group", "datum-pool"))) {
set_reply_text(str_reply, "%s\ndatum tx %s is placed in datum pool ", str_reply_tmp, l_key_str);
dap_chain_utxo_tx_add((dap_chain_datum_tx_t*)l_datum_tx->data);
else{
set_reply_text(str_reply, "%s\ndatum tx %s is not placed in datum pool ", str_reply_tmp, l_key_str);
return -2;
}
DAP_DELETE(str_reply_tmp);
DAP_DELETE(l_key_str);
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
/**
* com_tx_cond_create command
*
* Create transaction
*/
int com_tx_cond_create(int argc, const char ** argv, char **str_reply)
{
// test
const char * l_token_ticker = NULL;
const char *c_wallets_path = dap_config_get_item_str(g_config, "general", "wallets_path");
const char *c_wallet_name_from = "w_tesla"; // where to take coins for service
const char *c_wallet_name_cond = "w_picnic"; // who will be use service, usually the same address (addr_from)
int l_value = 50;
dap_chain_wallet_t *l_wallet_from = dap_chain_wallet_open(c_wallet_name_from, c_wallets_path);
dap_enc_key_t *l_key = dap_chain_wallet_get_key(l_wallet_from, 0);
dap_chain_wallet_t *l_wallet_cond = dap_chain_wallet_open(c_wallet_name_cond, c_wallets_path);
dap_enc_key_t *l_key_cond = dap_chain_wallet_get_key(l_wallet_from, 0);
// where to take coins for service
const dap_chain_addr_t *addr_from = dap_chain_wallet_get_addr(l_wallet_from);
// who will be use service, usually the same address (addr_from)
const dap_chain_addr_t *addr_cond = dap_chain_wallet_get_addr(l_wallet_cond);
dap_chain_net_srv_abstract_t l_cond;
l_cond.price = l_value;
int res = dap_chain_mempool_tx_create_cond(l_key, l_key_cond, (dap_chain_addr_t*) addr_from,
(dap_chain_addr_t*) addr_cond,
NULL, l_token_ticker, l_value, 0, (const void*) &l_cond, sizeof(dap_chain_net_srv_abstract_t));
dap_chain_wallet_close(l_wallet_from);
dap_chain_wallet_close(l_wallet_cond);
set_reply_text(str_reply, "tx_cond_create res=%d", res);
if(res == 1)
return 0;
return -1;
}
/**
* com_tx_create command
*
* Create transaction
*/
int com_tx_create(int argc, const char ** argv, char **str_reply)
{
int arg_index = 1;
int cmd_num = 1;
const char *value_str = NULL;
const char *addr_base58_to = NULL;
const char *addr_base58_fee = NULL;
const char *str_tmp = NULL;
const char * l_from_wallet_name = NULL;
const char * l_token_ticker = NULL;
uint64_t value = 0;
uint64_t value_fee = 0;
find_option_val(argv, arg_index, argc, "from_wallet_name", &l_from_wallet_name);
find_option_val(argv, arg_index, argc, "to_addr", &addr_base58_to);
find_option_val(argv, arg_index, argc, "token", &l_token_ticker);
if(find_option_val(argv, arg_index, argc, "fee", &addr_base58_fee)) {
if(find_option_val(argv, arg_index, argc, "value_fee", &str_tmp)) {
value_fee = strtoull(str_tmp, NULL, 10);
}
}
if(find_option_val(argv, arg_index, argc, "value", &str_tmp)) {
if(!l_from_wallet_name) {
set_reply_text(str_reply, "tx_create requires parameter 'from_wallet_name'");
return -1;
}
if(!addr_base58_to) {
set_reply_text(str_reply, "tx_create requires parameter 'to_addr'");
return -1;
}
if(!value) {
set_reply_text(str_reply, "tx_create requires parameter 'value'");
return -1;
}
if(addr_base58_fee && !value_fee) {
set_reply_text(str_reply, "tx_create requires parameter 'value_fee' if 'fee' is specified");
return -1;
}
const char *c_wallets_path = dap_config_get_item_str(g_config, "general", "wallets_path");
dap_chain_wallet_t * l_wallet = dap_chain_wallet_open(l_from_wallet_name, c_wallets_path);
if(!l_wallet) {
set_reply_text(str_reply, "wallet %s does not exist", l_from_wallet_name);
return -1;
}
/* //debug
{
dap_chain_wallet_t * l_wallet_tesla = dap_chain_wallet_open("w_tesla", c_wallets_path);
const dap_chain_addr_t *l_addr_tesla = dap_chain_wallet_get_addr(l_wallet_tesla);
char *addr = dap_chain_addr_to_str(l_addr_tesla);
addr = 0;
}*/
const dap_chain_addr_t *addr_from = (const dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
dap_chain_addr_t *addr_to = dap_chain_str_to_addr(addr_base58_to);
dap_chain_addr_t *addr_fee = dap_chain_str_to_addr(addr_base58_fee);
if(!addr_from) {
set_reply_text(str_reply, "source address is invalid");
return -1;
}
if(!addr_to) {
set_reply_text(str_reply, "destination address is invalid");
return -1;
}
if(addr_base58_fee && !addr_fee) {
set_reply_text(str_reply, "fee address is invalid");
return -1;
}
dap_string_t *string_ret = dap_string_new(NULL);
//g_string_printf(string_ret, "from=%s\nto=%s\nval=%lld\nfee=%s\nval_fee=%lld\n\n",
// addr_base58_from, addr_base58_to, value, addr_base58_fee, value_fee);
int res = dap_chain_mempool_tx_create(dap_chain_wallet_get_key(l_wallet, 0), addr_from, addr_to, addr_fee,
l_token_ticker, value, value_fee);
dap_string_append_printf(string_ret, "transfer=%s\n", (res == 0) ? "Ok" : (res==-2)? "False, not enough funds for transfer" : "False");
char *str_ret_tmp = dap_string_free(string_ret, false);
char *str_ret = strdup(str_ret_tmp);
set_reply_text(str_reply, str_ret);
DAP_DELETE(addr_to);
DAP_DELETE(addr_fee);
/**
* tx_verify command
*
* Verifing transaction
*/
int com_tx_verify(int argc, const char ** argv, char **str_reply)
{
if(argc > 1) {
const COMMAND *cmd = find_command(argv[1]);
if(cmd)
{
if(str_reply)
*str_reply = dap_strdup(cmd->doc);
return 1;
}
if(str_reply)
set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]);
set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\"");