mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-03-13 06:01:45 +00:00
Implemented transfer RPC call.
This commit is contained in:
parent
350f6fa953
commit
b39ed3748d
@ -1221,6 +1221,133 @@ UniValue sendmany(const JSONRPCRequest& request)
|
|||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static CAmount AmountFromIntegerValue(const UniValue& value)
|
||||||
|
{
|
||||||
|
if (!value.isNum())
|
||||||
|
throw std::runtime_error("Amount is not a number or string");
|
||||||
|
CAmount amount = value.get_int64();
|
||||||
|
if (!MoneyRange(amount))
|
||||||
|
throw std::runtime_error("Amount out of range");
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cryptnote JSON RPC
|
||||||
|
UniValue transfer(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||||
|
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||||
|
return NullUniValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 12)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"transfer [{\"address\":amount,...}, ...] \n"
|
||||||
|
"\nSend multiple times. Amounts are in atomic units."
|
||||||
|
+ HelpRequiringPassphrase(pwallet) + "\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"destinations\" (string, required) A json object with addresses and amounts\n"
|
||||||
|
" [{\n"
|
||||||
|
" \"address\":address (string) The kevacoin address\n"
|
||||||
|
" \"amount\":amount (numeric) The numeric amount in atomic unut\n"
|
||||||
|
" ,...\n"
|
||||||
|
" }, ...]\n"
|
||||||
|
"\nResult:\n"
|
||||||
|
"\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
|
||||||
|
" the number of addresses.\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
"\nSend two amounts to two different addresses:\n"
|
||||||
|
+ HelpExampleCli("sendmany", "\"\" \"{\\\"LEr4hNAefWYhBMgxCFP2Po1NPrUeiK8kM2\\\":0.01,\\\"LbhhnrHHVFP1eUjP1tdNIYeEVsNHfN9FCw\\\":0.02}\"") +
|
||||||
|
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
|
||||||
|
+ HelpExampleCli("sendmany", "\"\" \"{\\\"LEr4hNAefWYhBMgxCFP2Po1NPrUeiK8kM2\\\":0.01,\\\"LbhhnrHHVFP1eUjP1tdNIYeEVsNHfN9FCw\\\":0.02}\" 6 \"testing\"") +
|
||||||
|
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
|
||||||
|
+ HelpExampleCli("sendmany", "\"\" \"{\\\"LEr4hNAefWYhBMgxCFP2Po1NPrUeiK8kM2\\\":0.01,\\\"LbhhnrHHVFP1eUjP1tdNIYeEVsNHfN9FCw\\\":0.02}\" 1 \"\" \"[\\\"LEr4hNAefWYhBMgxCFP2Po1NPrUeiK8kM2\\\",\\\"LbhhnrHHVFP1eUjP1tdNIYeEVsNHfN9FCw\\\"]\"") +
|
||||||
|
"\nAs a json rpc call\n"
|
||||||
|
+ HelpExampleRpc("sendmany", "\"\", {\"LEr4hNAefWYhBMgxCFP2Po1NPrUeiK8kM2\":0.01,\"LbhhnrHHVFP1eUjP1tdNIYeEVsNHfN9FCw\":0.02}, 6, \"testing\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
ObserveSafeMode();
|
||||||
|
|
||||||
|
// Make sure the results are valid at least up to the most recent block
|
||||||
|
// the user could have gotten from another RPC command prior to now
|
||||||
|
pwallet->BlockUntilSyncedToCurrentChain();
|
||||||
|
|
||||||
|
LOCK2(cs_main, pwallet->cs_wallet);
|
||||||
|
|
||||||
|
if (pwallet->GetBroadcastTransactions() && !g_connman) {
|
||||||
|
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue sendToList = request.params[0].get_array();
|
||||||
|
|
||||||
|
CWalletTx wtx;
|
||||||
|
CCoinControl coin_control;
|
||||||
|
std::set<CTxDestination> destinations;
|
||||||
|
std::vector<CRecipient> vecSend;
|
||||||
|
|
||||||
|
CAmount totalAmount = 0;
|
||||||
|
for (unsigned int idx = 0; idx < sendToList.size(); idx++) {
|
||||||
|
const UniValue& sendTo = sendToList[idx].get_obj();
|
||||||
|
const UniValue& addr = find_value(sendTo, "address");
|
||||||
|
if (addr.isNull()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, missing address: "));
|
||||||
|
}
|
||||||
|
std::string addrStr = addr.get_str();
|
||||||
|
CTxDestination dest = DecodeDestination(addrStr);
|
||||||
|
if (!IsValidDestination(dest)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Kevacoin address: ") + addrStr);
|
||||||
|
}
|
||||||
|
if (destinations.count(dest)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + addrStr);
|
||||||
|
}
|
||||||
|
destinations.insert(dest);
|
||||||
|
|
||||||
|
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||||
|
const UniValue& amount = find_value(sendTo, "amount");
|
||||||
|
CAmount nAmount = AmountFromIntegerValue(amount);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
|
totalAmount += nAmount;
|
||||||
|
|
||||||
|
CRecipient recipient = {scriptPubKey, nAmount, false};
|
||||||
|
vecSend.push_back(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureWalletIsUnlocked(pwallet);
|
||||||
|
|
||||||
|
// Check funds
|
||||||
|
CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, 1, nullptr);
|
||||||
|
if (totalAmount > nBalance)
|
||||||
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
|
||||||
|
|
||||||
|
// Send
|
||||||
|
CReserveKey keyChange(pwallet);
|
||||||
|
CAmount nFeeRequired = 0;
|
||||||
|
int nChangePosRet = -1;
|
||||||
|
std::string strFailReason;
|
||||||
|
std::vector<unsigned char> empty;
|
||||||
|
bool fCreated = pwallet->CreateTransaction(vecSend, nullptr, empty, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
|
||||||
|
if (!fCreated)
|
||||||
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
||||||
|
CValidationState state;
|
||||||
|
if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
|
||||||
|
strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
|
||||||
|
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.push_back(Pair("amount", (uint64_t)totalAmount));
|
||||||
|
result.push_back(Pair("fee", (uint64_t)nFeeRequired));
|
||||||
|
result.push_back(Pair("multisig_txset", ""));
|
||||||
|
result.push_back(Pair("tx_blob", ""));
|
||||||
|
result.push_back(Pair("tx_hash", wtx.GetHash().GetHex()));
|
||||||
|
result.push_back(Pair("tx_key", ""));
|
||||||
|
result.push_back(Pair("tx_metadata", ""));
|
||||||
|
result.push_back(Pair("unsigned_txset", ""));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue addmultisigaddress(const JSONRPCRequest& request)
|
UniValue addmultisigaddress(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||||
@ -3658,6 +3785,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
|
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
|
||||||
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
|
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
|
||||||
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
|
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
|
||||||
|
{ "wallet", "transfer", &transfer, {"destinations"} },
|
||||||
|
|
||||||
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
|
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user