diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index a73e28b2ed..e55714f42c 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -437,6 +437,12 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ } else if ( strcmp(method,"inuse") == 0 ) return(jprint(LP_inuse_json(),1)); +#ifndef NOTETOMIC + else if ( strcmp(method,"eth_gas_price") == 0 ) + { + return LP_eth_gas_price(ptr); + } +#endif else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 ) return(retstr); if ( base[0] != 0 && rel[0] != 0 ) diff --git a/iguana/exchanges/LP_etomic.c b/iguana/exchanges/LP_etomic.c index c6f135a42f..5c1e50e63c 100644 --- a/iguana/exchanges/LP_etomic.c +++ b/iguana/exchanges/LP_etomic.c @@ -42,9 +42,9 @@ char *LP_etomicalice_send_fee(struct basilisk_swap *swap) uint8arrayToHex(secretKey, swap->persistent_privkey.bytes, 32); LP_etomic_pubkeystr_to_addr(INSTANTDEX_PUBKEY, dexaddr); if (strcmp(swap->I.alicestr,"ETH") == 0 ) { - return(sendEth(dexaddr, amount, secretKey, 1)); + return(sendEth(dexaddr, amount, secretKey, 1, 0, 0)); } else { - return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1)); + return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1, 0, 0)); } } diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index c1489a30af..615b03dd3b 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -1694,28 +1694,54 @@ char *LP_autosplit(struct iguana_info *coin) char *LP_eth_withdraw(struct iguana_info *coin,cJSON *argjson) { cJSON *retjson = cJSON_CreateObject(); + cJSON *gas_json = cJSON_GetObjectItem(argjson, "gas"); + cJSON *gas_price_json = cJSON_GetObjectItem(argjson, "gas_price"); char *dest_addr, *tx_id, privkey_str[70], amount_str[100]; - int64_t amount; + int64_t amount = 0, gas = 0, gas_price = 0; bits256 privkey; dest_addr = jstr(argjson, "to"); + if (dest_addr == NULL) { + return(clonestr("{\"error\":\"param 'to' is required!\"}")); + } amount = jdouble(argjson, "amount") * 100000000; + if (amount == 0) { + return(clonestr("{\"error\":\"'amount' is not set or equal to zero!\"}")); + } + if (gas_json != NULL && is_cJSON_Number(gas_json)) { + gas = gas_json->valueint; + if (gas < 21000) { + return (clonestr("{\"error\":\"'gas' can't be lower than 21000!\"}")); + } + } + if (gas_price_json != NULL && is_cJSON_Number(gas_price_json)) { + gas_price = gas_price_json->valueint; + if (gas_price < 1) { + return (clonestr("{\"error\":\"'gas_price' can't be lower than 1!\"}")); + } + } privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr); uint8arrayToHex(privkey_str, privkey.bytes, 32); satoshisToWei(amount_str, amount); if (strcmp(coin->symbol, "ETH") == 0) { - tx_id = sendEth(dest_addr, amount_str, privkey_str, 0); + tx_id = sendEth(dest_addr, amount_str, privkey_str, 0, gas, gas_price); } else { - tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0); + tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0, gas, gas_price); } jaddstr(retjson, "tx_id", tx_id); + free(tx_id); return(jprint(retjson,1)); } +char *LP_eth_gas_price() +{ + cJSON *retjson = cJSON_CreateObject(); + uint64_t gas_price = getGasPriceFromStation(); + cJSON_AddNumberToObject(retjson, "gas_price", gas_price); + return(jprint(retjson,1)); +} #endif - - int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr) { struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj; diff --git a/iguana/exchanges/etomicswap/etomiccurl.c b/iguana/exchanges/etomicswap/etomiccurl.c index e7f1296ee6..51dc9efc82 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.c +++ b/iguana/exchanges/etomicswap/etomiccurl.c @@ -186,7 +186,7 @@ char* getEthBalanceRequest(char* address) return balance; } -char* ethCall(char* to, const char* data) +char *ethCall(char *to, const char *data) { cJSON *params = cJSON_CreateArray(); cJSON *txObject = cJSON_CreateObject(); @@ -205,6 +205,26 @@ char* ethCall(char* to, const char* data) return result; } +uint64_t estimateGas(char *from, char *to, const char *data) +{ + cJSON *params = cJSON_CreateArray(); + cJSON *txObject = cJSON_CreateObject(); + cJSON_AddStringToObject(txObject, "from", from); + cJSON_AddStringToObject(txObject, "to", to); + cJSON_AddStringToObject(txObject, "data", data); + cJSON_AddItemToArray(params, txObject); + cJSON_AddItemToArray(params, cJSON_CreateString("latest")); + cJSON *resultJson = sendRpcRequest("eth_estimateGas", params); + cJSON_Delete(params); + uint64_t result = 0; + if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) { + result = (uint64_t)strtoul(resultJson->valuestring, NULL, 0); + result = (result / 100) * 120; // add 20% because real gas usage might differ from estimate + } + cJSON_Delete(resultJson); + return result; +} + EthTxReceipt getEthTxReceipt(char *txId) { EthTxReceipt result; diff --git a/iguana/exchanges/etomicswap/etomiccurl.h b/iguana/exchanges/etomicswap/etomiccurl.h index c0433bc75c..ef58f82fa4 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.h +++ b/iguana/exchanges/etomicswap/etomiccurl.h @@ -39,6 +39,7 @@ typedef struct char* sendRawTx(char* rawTx); char* sendRawTxWaitConfirm(char* rawTx); char* ethCall(char* to, const char* data); +uint64_t estimateGas(char *from, char *to, const char *data); int64_t getNonce(char* address); char* getEthBalanceRequest(char* address); EthTxReceipt getEthTxReceipt(char *txId); diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp index 204848477c..f19f9c8ae3 100644 --- a/iguana/exchanges/etomicswap/etomiclib.cpp +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -582,15 +582,23 @@ uint64_t weiToSatoshi(char *wei) return static_cast(satoshi); } -char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm) +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice) { TransactionSkeleton tx; char *from = privKey2Addr(privKey), *result; tx.from = jsToAddress(from); tx.to = jsToAddress(to); tx.value = jsToU256(amount); - tx.gas = 21000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + if (gas > 0) { + tx.gas = gas; + } else { + tx.gas = 21000; + } + if (gasPrice > 0) { + tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9); + } else { + tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + } tx.nonce = getNonce(from); free(from); @@ -620,19 +628,33 @@ std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amoun return ss; } -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm) +char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice) { TransactionSkeleton tx; char *from = privKey2Addr(privKey), *result; + std::stringstream ss = getErc20TransferData(tokenAddress, to, amount); + tx.from = jsToAddress(from); tx.to = jsToAddress(tokenAddress); tx.value = 0; - tx.gas = 60000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + if (gas > 0) { + tx.gas = gas; + } else { + uint64_t gasEstimation = estimateGas(from, tokenAddress, ss.str().c_str()); + if (gasEstimation > 0) { + tx.gas = gasEstimation; + } else { + tx.gas = 150000; + } + } + if (gasPrice > 0) { + tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9); + } else { + tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + } tx.nonce = getNonce(from); free(from); - std::stringstream ss = getErc20TransferData(tokenAddress, to, amount); tx.data = jsToBytes(ss.str()); char *rawTx = signTx(tx, privKey); diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h index c7b846ddbb..f409f93818 100644 --- a/iguana/exchanges/etomicswap/etomiclib.h +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -177,8 +177,8 @@ void uint8arrayToHex(char *dest, uint8_t *input, int len); void satoshisToWei(char *dest, uint64_t input); uint64_t weiToSatoshi(char *wei); -char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm); -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm); +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice); +char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice); uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data); // Your prototype or Definition