diff --git a/src/omnicore/convert.h b/src/omnicore/convert.h index 9916cba5aaa69..39d8695d3107d 100644 --- a/src/omnicore/convert.h +++ b/src/omnicore/convert.h @@ -22,19 +22,6 @@ void swapByteOrder16(uint16_t&); void swapByteOrder32(uint32_t&); void swapByteOrder64(uint64_t&); -/** - * Pushes bytes to the end of a vector. - */ -#define PUSH_BACK_BYTES(vector, value)\ - vector.insert(vector.end(), reinterpret_cast(&(value)),\ - reinterpret_cast(&(value)) + sizeof((value))); - -/** - * Pushes bytes to the end of a vector based on a pointer. - */ -#define PUSH_BACK_BYTES_PTR(vector, ptr, size)\ - vector.insert(vector.end(), reinterpret_cast((ptr)),\ - reinterpret_cast((ptr)) + (size)); } diff --git a/src/omnicore/createpayload.cpp b/src/omnicore/createpayload.cpp index c3d8beec2d4c1..230920c6ee0de 100644 --- a/src/omnicore/createpayload.cpp +++ b/src/omnicore/createpayload.cpp @@ -8,6 +8,21 @@ #include #include +/** + * Pushes bytes to the end of a vector. + */ +#define PUSH_BACK_BYTES(vector, value)\ + vector.insert(vector.end(), reinterpret_cast(&(value)),\ + reinterpret_cast(&(value)) + sizeof((value))); + +/** + * Pushes bytes to the end of a vector based on a pointer. + */ +#define PUSH_BACK_BYTES_PTR(vector, ptr, size)\ + vector.insert(vector.end(), reinterpret_cast((ptr)),\ + reinterpret_cast((ptr)) + (size)); + + std::vector CreatePayload_SimpleSend(uint32_t propertyId, uint64_t amount) { std::vector payload; @@ -277,16 +292,103 @@ std::vector CreatePayload_ChangeIssuer(uint32_t propertyId) return payload; } -std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired, uint8_t action) +std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired) { std::vector payload; + uint16_t messageType = 21; uint16_t messageVer = 0; + uint8_t action = 1; // ADD + + mastercore::swapByteOrder16(messageVer); mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder32(propertyIdForSale); + mastercore::swapByteOrder64(amountForSale); + mastercore::swapByteOrder32(propertyIdDesired); + mastercore::swapByteOrder64(amountDesired); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyIdForSale); + PUSH_BACK_BYTES(payload, amountForSale); + PUSH_BACK_BYTES(payload, propertyIdDesired); + PUSH_BACK_BYTES(payload, amountDesired); + PUSH_BACK_BYTES(payload, action); + + return payload; +} + +std::vector CreatePayload_MetaDExCancelPrice(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired) +{ + std::vector payload; + + uint16_t messageType = 21; + uint16_t messageVer = 0; + uint8_t action = 2; // CANCEL_AT_PRICE + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder16(messageType); mastercore::swapByteOrder32(propertyIdForSale); + mastercore::swapByteOrder64(amountForSale); mastercore::swapByteOrder32(propertyIdDesired); + mastercore::swapByteOrder64(amountDesired); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyIdForSale); + PUSH_BACK_BYTES(payload, amountForSale); + PUSH_BACK_BYTES(payload, propertyIdDesired); + PUSH_BACK_BYTES(payload, amountDesired); + PUSH_BACK_BYTES(payload, action); + + return payload; +} + +std::vector CreatePayload_MetaDExCancelPair(uint32_t propertyIdForSale, uint32_t propertyIdDesired) +{ + std::vector payload; + + uint16_t messageType = 21; + uint16_t messageVer = 0; + uint64_t amountForSale = 0; + uint64_t amountDesired = 0; + uint8_t action = 3; // CANCEL_ALL_FOR_PAIR + + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder32(propertyIdForSale); + mastercore::swapByteOrder64(amountForSale); + mastercore::swapByteOrder32(propertyIdDesired); + mastercore::swapByteOrder64(amountDesired); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyIdForSale); + PUSH_BACK_BYTES(payload, amountForSale); + PUSH_BACK_BYTES(payload, propertyIdDesired); + PUSH_BACK_BYTES(payload, amountDesired); + PUSH_BACK_BYTES(payload, action); + + return payload; +} + +std::vector CreatePayload_MetaDExCancelEcosystem(uint8_t ecosystem) +{ + std::vector payload; + + uint16_t messageType = 21; + uint16_t messageVer = 0; + uint32_t propertyIdForSale = ecosystem; + uint64_t amountForSale = 0; + uint32_t propertyIdDesired = ecosystem; + uint64_t amountDesired = 0; + uint8_t action = 4; // CANCEL_EVERYTHING + + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder32(propertyIdForSale); mastercore::swapByteOrder64(amountForSale); + mastercore::swapByteOrder32(propertyIdDesired); mastercore::swapByteOrder64(amountDesired); PUSH_BACK_BYTES(payload, messageVer); @@ -300,4 +402,6 @@ std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale return payload; } +#undef PUSH_BACK_BYTES +#undef PUSH_BACK_BYTES_PTR diff --git a/src/omnicore/createpayload.h b/src/omnicore/createpayload.h index 6968cdc87d67c..88d468d696185 100644 --- a/src/omnicore/createpayload.h +++ b/src/omnicore/createpayload.h @@ -20,7 +20,10 @@ std::vector CreatePayload_CloseCrowdsale(uint32_t propertyId); std::vector CreatePayload_Grant(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_Revoke(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_ChangeIssuer(uint32_t propertyId); -std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired, uint8_t action); +std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); +std::vector CreatePayload_MetaDExCancelPrice(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); +std::vector CreatePayload_MetaDExCancelPair(uint32_t propertyIdForSale, uint32_t propertyIdDesired); +std::vector CreatePayload_MetaDExCancelEcosystem(uint8_t ecosystem); #endif // OMNICORE_CREATEPAYLOAD_H diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index 187e44fdf0f84..26555747e46da 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -704,64 +704,283 @@ Value sendclosecrowdsale_OMNI(const Array& params, bool fHelp) } } -// sendtrade_OMNI - MetaDEx trade -Value sendtrade_OMNI(const Array& params, bool fHelp) +// trade_MP - MetaDEx trade +Value trade_MP(const Array& params, bool fHelp) { if (fHelp || params.size() != 6) throw runtime_error( - "sendtrade_OMNI \"fromaddress\" propertyidforsale \"amountforsale\" propertiddesired \"amountdesired\" action\n" - "\nPlace or cancel a trade offer on the distributed token exchange.\n" + "trade_MP \"fromaddress\" propertyidforsale \"amountforsale\" propertiddesired \"amountdesired\" action\n" + "\nNote: this command is depreciated, and was replaced by:\n" + " - sendtrade_OMNI\n" + " - sendcanceltradebyprice_OMNI\n" + " - sendcanceltradebypair_OMNI\n" + " - sendcanceltradebypair_OMNI\n" + ); + + Array values; + uint8_t action = params[5].get_int64(); + + // Forward to the new commands, based on action value + switch (action) { + case CMPTransaction::ADD: + { + values.push_back(params[0]); // fromAddress + values.push_back(params[1]); // propertyIdForSale + values.push_back(params[2]); // amountForSale + values.push_back(params[3]); // propertyIdDesired + values.push_back(params[4]); // amountDesired + return sendtrade_OMNI(values, fHelp); + } + case CMPTransaction::CANCEL_AT_PRICE: + { + values.push_back(params[0]); // fromAddress + values.push_back(params[1]); // propertyIdForSale + values.push_back(params[2]); // amountForSale + values.push_back(params[3]); // propertyIdDesired + values.push_back(params[4]); // amountDesired + return sendcanceltradesbyprice_OMNI(values, fHelp); + } + case CMPTransaction::CANCEL_ALL_FOR_PAIR: + { + values.push_back(params[0]); // fromAddress + values.push_back(params[1]); // propertyIdForSale + values.push_back(params[3]); // propertyIdDesired + return sendcanceltradesbypair_OMNI(values, fHelp); + } + case CMPTransaction::CANCEL_EVERYTHING: + { + uint8_t ecosystem = 0; + if (isMainEcosystemProperty(params[1].get_int64()) + && isMainEcosystemProperty(params[3].get_int64())) { + ecosystem = OMNI_PROPERTY_MSC; + } + if (isTestEcosystemProperty(params[1].get_int64()) + && isTestEcosystemProperty(params[3].get_int64())) { + ecosystem = OMNI_PROPERTY_TMSC; + } + values.push_back(params[0]); // fromAddress + values.push_back(ecosystem); + return sendcancelalltrades_OMNI(values, fHelp); + } + } + + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid action (1,2,3,4 only)"); +} + +// Send a new MetaDEx trade +Value sendtrade_OMNI(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 5) + throw runtime_error( + "sendtrade_OMNI \"fromaddress\" propertyidforsale \"amountforsale\" propertiddesired \"amountdesired\"\n" + "\nPlace a trade offer on the distributed token exchange.\n" "\nParameters:\n" "FromAddress : the address to send this transaction from\n" "PropertyIDForSale : the property to list for sale\n" "AmountForSale : the amount to list for sale\n" "PropertyIDDesired : the property desired\n" "AmountDesired : the amount desired\n" - "Action : the action to take: (1) new, (2) cancel by price, (3) cancel by pair, (4) cancel all\n" "Result:\n" "txid (string) The transaction ID of the sent transaction\n" "\nExamples:\n" - ">omnicored sendtrade_OMNI \"1FromAddress\" PropertyIDForSale \"AmountForSale\" PropertyIDDesired \"AmountDesired\" Action\n" + ">omnicored sendtrade_OMNI \"1FromAddress\" PropertyIDForSale \"AmountForSale\" PropertyIDDesired \"AmountDesired\"\n" ); // obtain parameters & info std::string fromAddress = params[0].get_str(); - unsigned int propertyIdForSale = int64Touint32Safe(params[1].get_int64()); - string strAmountForSale = params[2].get_str(); - unsigned int propertyIdDesired = int64Touint32Safe(params[3].get_int64()); - string strAmountDesired = params[4].get_str(); - int64_t action = params[5].get_int64(); + uint32_t propertyIdForSale = int64Touint32Safe(params[1].get_int64()); + std::string strAmountForSale = params[2].get_str(); + uint32_t propertyIdDesired = int64Touint32Safe(params[3].get_int64()); + std::string strAmountDesired = params[4].get_str(); + + CMPSPInfo::Entry spForSale; + CMPSPInfo::Entry spDesired; + if (false == _my_sps->getSP(propertyIdForSale, spForSale)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale does not exist"); + if (false == _my_sps->getSP(propertyIdDesired, spDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property desired does not exist"); + if (isTestEcosystemProperty(propertyIdForSale) != isTestEcosystemProperty(propertyIdDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be in the same ecosystem"); + if (propertyIdForSale == propertyIdDesired) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be different"); + + int64_t amountForSale = StrToInt64(strAmountForSale, spForSale.isDivisible()); + int64_t amountDesired = StrToInt64(strAmountDesired, spDesired.isDivisible()); + if (0 >= amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for sale"); + if (!isRangeOK(amountForSale)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount for sale not in range"); + if (0 >= amountDesired) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount desired"); + if (!isRangeOK(amountDesired)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount desired not in range"); + const int64_t senderBalance = getMPbalance(fromAddress, propertyIdForSale, BALANCE); const int64_t senderAvailableBalance = getUserAvailableMPbalance(fromAddress, propertyIdForSale); + if (senderBalance < amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Sender has insufficient balance"); + if (senderAvailableBalance < amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Sender has insufficient balance (due to pending transactions)"); + + // create a payload for the transaction + std::vector payload = CreatePayload_MetaDExTrade(propertyIdForSale, amountForSale, propertyIdDesired, amountDesired); + + // request the wallet build the transaction (and if needed commit it) + uint256 txid = 0; + std::string rawHex; + int result = ClassAgnosticWalletTXBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + uint8_t action = CMPTransaction::ADD; // TODO: move into pending creation + PendingAdd(txid, fromAddress, "", MSC_TYPE_METADEX, propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); + return txid.GetHex(); + } + } +} + +// Cancel MetaDEx by price +Value sendcanceltradesbyprice_OMNI(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 5) + throw runtime_error( + "sendcanceltradesbyprice_OMNI \"fromaddress\" propertyidforsale \"amountforsale\" propertiddesired \"amountdesired\"\n" + "\nCancel offers on the distributed token exchange with the given price.\n" + "\nParameters:\n" + "FromAddress : the address to send this transaction from\n" + "PropertyIDForSale : the property listed for sale\n" + "AmountForSale : the amount listed for sale\n" + "PropertyIDDesired : the property desired\n" + "AmountDesired : the desired amount\n" + "Result:\n" + "txid (string) The transaction ID of the sent transaction\n" + "\nExamples:\n" + ">omnicored sendcanceltradesbyprice_OMNI \"1FromAddress\" PropertyIDForSale \"AmountForSale\" PropertyIDDesired \"AmountDesired\"\n" + ); + + // obtain parameters & info + std::string fromAddress = params[0].get_str(); + uint32_t propertyIdForSale = int64Touint32Safe(params[1].get_int64()); + std::string strAmountForSale = params[2].get_str(); + uint32_t propertyIdDesired = int64Touint32Safe(params[3].get_int64()); + std::string strAmountDesired = params[4].get_str(); - // setup a few vars - int64_t amountForSale = 0, amountDesired = 0; CMPSPInfo::Entry spForSale; CMPSPInfo::Entry spDesired; + if (false == _my_sps->getSP(propertyIdForSale, spForSale)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale does not exist"); + if (false == _my_sps->getSP(propertyIdDesired, spDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property desired does not exist"); + if (isTestEcosystemProperty(propertyIdForSale) != isTestEcosystemProperty(propertyIdDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be in the same ecosystem"); + if (propertyIdForSale == propertyIdDesired) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be different"); + + int64_t amountForSale = StrToInt64(strAmountForSale, spForSale.isDivisible()); + int64_t amountDesired = StrToInt64(strAmountDesired, spDesired.isDivisible()); + if (0 >= amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for sale"); + if (!isRangeOK(amountForSale)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount for sale not in range"); + if (0 >= amountDesired) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount desired"); + if (!isRangeOK(amountDesired)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount desired not in range"); + + // TODO: check, if there are matching offers to cancel + + // create a payload for the transaction + std::vector payload = CreatePayload_MetaDExCancelPrice(propertyIdForSale, amountForSale, propertyIdDesired, amountDesired); - // perform conversions & checks - if (action <= 0 || CMPTransaction::CANCEL_EVERYTHING < action) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid action (1,2,3,4 only)"); - if (action != CMPTransaction::CANCEL_EVERYTHING) { // these checks are not applicable to cancel everything - if (false == _my_sps->getSP(propertyIdForSale, spForSale)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale does not exist"); - if (false == _my_sps->getSP(propertyIdDesired, spDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property desired does not exist"); - if (isTestEcosystemProperty(propertyIdForSale) != isTestEcosystemProperty(propertyIdDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be in the same ecosystem"); - if (propertyIdForSale == propertyIdDesired) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be different"); + // request the wallet build the transaction (and if needed commit it) + uint256 txid = 0; + std::string rawHex; + int result = ClassAgnosticWalletTXBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + uint8_t action = CMPTransaction::CANCEL_AT_PRICE; // TODO: move into pending creation + PendingAdd(txid, fromAddress, "", MSC_TYPE_METADEX, propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); + return txid.GetHex(); + } } - if (action <= CMPTransaction::CANCEL_AT_PRICE) { // cancel pair and cancel everything permit zero values - amountForSale = StrToInt64(strAmountForSale, spForSale.isDivisible()); - amountDesired = StrToInt64(strAmountDesired, spDesired.isDivisible()); - if (0 >= amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for sale"); - if (!isRangeOK(amountForSale)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount for sale not in range"); - if (0 >= amountDesired) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount desired"); - if (!isRangeOK(amountDesired)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount desired not in range"); +} + +// Cancel MetaDEx orders by currency pair +Value sendcanceltradesbypair_OMNI(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "sendcanceltradesbypair_OMNI \"fromaddress\" propertyidforsale propertiddesired\n" + "\nCancel offers on the distributed token exchange with the given currency pair.\n" + "\nParameters:\n" + "FromAddress : the address to send this transaction from\n" + "PropertyIDForSale : the property listed for sale\n" + "PropertyIDDesired : the property desired\n" + "Result:\n" + "txid (string) The transaction ID of the sent transaction\n" + "\nExamples:\n" + ">omnicored sendcanceltradesbypair_OMNI \"1FromAddress\" PropertyIDForSale \"AmountForSale\" PropertyIDDesired \"AmountDesired\"\n" + ); + + // obtain parameters & info + std::string fromAddress = params[0].get_str(); + uint32_t propertyIdForSale = int64Touint32Safe(params[1].get_int64()); + uint32_t propertyIdDesired = int64Touint32Safe(params[2].get_int64()); + + CMPSPInfo::Entry spForSale; + CMPSPInfo::Entry spDesired; + if (false == _my_sps->getSP(propertyIdForSale, spForSale)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale does not exist"); + if (false == _my_sps->getSP(propertyIdDesired, spDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property desired does not exist"); + if (isTestEcosystemProperty(propertyIdForSale) != isTestEcosystemProperty(propertyIdDesired)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be in the same ecosystem"); + if (propertyIdForSale == propertyIdDesired) throw JSONRPCError(RPC_INVALID_PARAMETER, "Property for sale and property desired must be different"); + + // TODO: check, if there are matching offers to cancel + + // create a payload for the transaction + std::vector payload = CreatePayload_MetaDExCancelPair(propertyIdForSale, propertyIdDesired); + + // request the wallet build the transaction (and if needed commit it) + uint256 txid = 0; + std::string rawHex; + int result = ClassAgnosticWalletTXBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + uint8_t action = CMPTransaction::CANCEL_ALL_FOR_PAIR; // TODO: move into pending creation + int64_t amountForSale = 0; + int64_t amountDesired = 0; + PendingAdd(txid, fromAddress, "", MSC_TYPE_METADEX, propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); + return txid.GetHex(); + } } - if (action == CMPTransaction::ADD) { // only check for sufficient balance for new trades - if (senderBalance < amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Sender has insufficient balance"); - if (senderAvailableBalance < amountForSale) throw JSONRPCError(RPC_TYPE_ERROR, "Sender has insufficient balance (due to pending transactions)"); +} + +// Cancel MetaDEx orders by ecosystem +Value sendcancelalltrades_OMNI(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "sendcancelalltrades_OMNI \"fromaddress\" ecosystem\n" + "\nCancel all offers on the distributed token exchange in the given ecosystem.\n" + "\nParameters:\n" + "FromAddress : the address to send this transaction from\n" + "Ecosystem : the ecosystem of the offers to cancel - (0) both, (1) main, (2) test\n" + "Result:\n" + "txid (string) The transaction ID of the sent transaction\n" + "\nExamples:\n" + ">omnicored sendcancelalltrades_OMNI \"1FromAddress\" Ecosystem\n" + ); + + // obtain parameters & info + std::string fromAddress = params[0].get_str(); + uint8_t ecosystem = params[1].get_uint64(); + + if (OMNI_PROPERTY_TMSC < ecosystem) { + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid ecosystem"); } + // TODO: check, if there are matching offers to cancel + // create a payload for the transaction - std::vector payload = CreatePayload_MetaDExTrade(propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); + std::vector payload = CreatePayload_MetaDExCancelEcosystem(ecosystem); // request the wallet build the transaction (and if needed commit it) uint256 txid = 0; @@ -775,6 +994,11 @@ Value sendtrade_OMNI(const Array& params, bool fHelp) if (!autoCommit) { return rawHex; } else { + uint8_t action = CMPTransaction::CANCEL_EVERYTHING; // TODO: move into pending creation + int64_t amountForSale = 0; + int64_t amountDesired = 0; + uint32_t propertyIdForSale = ecosystem; + uint32_t propertyIdDesired = ecosystem; PendingAdd(txid, fromAddress, "", MSC_TYPE_METADEX, propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); return txid.GetHex(); } diff --git a/src/omnicore/test/create_payload_tests.cpp b/src/omnicore/test/create_payload_tests.cpp index 8b37f0a395bc8..77823c734b7b4 100644 --- a/src/omnicore/test/create_payload_tests.cpp +++ b/src/omnicore/test/create_payload_tests.cpp @@ -45,20 +45,63 @@ BOOST_AUTO_TEST_CASE(payload_dex_offer) "00010014000000010000000005f5e1000000000001312d000a000000000000271001"); } -BOOST_AUTO_TEST_CASE(payload_meta_dex_offer) +BOOST_AUTO_TEST_CASE(payload_meta_dex_new_trade) { // Trade tokens for tokens [type 21, version 0] std::vector vch = CreatePayload_MetaDExTrade( static_cast(1), // property: MSC static_cast(250000000), // amount for sale: 2.5 MSC static_cast(31), // property desired: TetherUS - static_cast(5000000000), // amount desired: 50.0 TetherUS - static_cast(1)); // sub-action: new offer + static_cast(5000000000)); // amount desired: 50.0 TetherUS + // sub-action: (1) new-offer BOOST_CHECK_EQUAL(HexStr(vch), "0000001500000001000000000ee6b2800000001f000000012a05f20001"); } +BOOST_AUTO_TEST_CASE(payload_meta_dex_cancel_at_price) +{ + // Trade tokens for tokens [type 21, version 0] + std::vector vch = CreatePayload_MetaDExCancelPrice( + static_cast(1), // property: MSC + static_cast(250000000), // amount for sale: 2.5 MSC + static_cast(31), // property desired: TetherUS + static_cast(5000000000)); // amount desired: 50.0 TetherUS + // sub-action: (2) cancel-at-price + + BOOST_CHECK_EQUAL(HexStr(vch), + "0000001500000001000000000ee6b2800000001f000000012a05f20002"); +} + +BOOST_AUTO_TEST_CASE(payload_meta_dex_cancel_pair) +{ + // Trade tokens for tokens [type 21, version 0] + std::vector vch = CreatePayload_MetaDExCancelPair( + static_cast(1), // property: MSC + // amount for sale: 0.0 MSC + static_cast(31)); // property desired: TetherUS + // amount desired: 0.0 TetherUS + // sub-action: (3) cancel-pair + + BOOST_CHECK_EQUAL(HexStr(vch), + "000000150000000100000000000000000000001f000000000000000003"); +} + +BOOST_AUTO_TEST_CASE(payload_meta_dex_cancel_ecosystem) +{ + // Trade tokens for tokens [type 21, version 0] + std::vector vch = CreatePayload_MetaDExCancelEcosystem( + static_cast(1)); // ecosystem: Main + // property: MSC + // amount for sale: 0.0 MSC + // property desired: MSC + // amount for sale: 0.0 MSC + // sub-action: (4) cancel-ecosystem + + BOOST_CHECK_EQUAL(HexStr(vch), + "0000001500000001000000000000000000000001000000000000000004"); +} + BOOST_AUTO_TEST_CASE(payload_accept_dex_offer) { // Purchase tokens with bitcoins [type 22, version 0] diff --git a/src/qt/metadexcanceldialog.cpp b/src/qt/metadexcanceldialog.cpp index f21e015ee044a..15831cc7d3f7a 100755 --- a/src/qt/metadexcanceldialog.cpp +++ b/src/qt/metadexcanceldialog.cpp @@ -327,8 +327,21 @@ void MetaDExCancelDialog::SendCancelTransaction() return; } + // TODO: restructure and seperate // create a payload for the transaction - std::vector payload = CreatePayload_MetaDExTrade(propertyIdForSale, amountForSale, propertyIdDesired, amountDesired, action); + std::vector payload; + if (action == 2) { // CANCEL_AT_PRICE + payload = CreatePayload_MetaDExCancelPrice(propertyIdForSale, amountForSale, propertyIdDesired, amountDesired); + } + if (action == 3) { // CANCEL_ALL_FOR_PAIR + payload = CreatePayload_MetaDExCancelPair(propertyIdForSale, propertyIdDesired); + } + if (action == 4) { // CANCEL_ALL_FOR_PAIR + uint8_t ecosystem = 0; + if (isMainEcosystemProperty(propertyIdForSale) && isMainEcosystemProperty(propertyIdDesired)) ecosystem = OMNI_PROPERTY_MSC; + if (isTestEcosystemProperty(propertyIdForSale) && isTestEcosystemProperty(propertyIdDesired)) ecosystem = OMNI_PROPERTY_TMSC; + payload = CreatePayload_MetaDExCancelEcosystem(ecosystem); + } // request the wallet build the transaction (and if needed commit it) uint256 txid = 0; diff --git a/src/qt/metadexdialog.cpp b/src/qt/metadexdialog.cpp index ff508656a0ec3..5ae59b40f2292 100755 --- a/src/qt/metadexdialog.cpp +++ b/src/qt/metadexdialog.cpp @@ -607,7 +607,7 @@ void MetaDExDialog::sendTrade(bool sell) } // create a payload for the transaction - std::vector payload = CreatePayload_MetaDExTrade(propertyIdSell, amountSell, propertyIdDes, amountDes, 1); + std::vector payload = CreatePayload_MetaDExTrade(propertyIdSell, amountSell, propertyIdDes, amountDes); // request the wallet build the transaction (and if needed commit it) uint256 txid = 0; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index d291f51f9b49c..602a70502657d 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -104,9 +104,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getallbalancesforid_MP", 0 }, { "listblocktransactions_MP", 0 }, { "setautocommit_OMNI", 0 }, - { "trade_MP", 2 }, - { "trade_MP", 4 }, - { "trade_MP", 5 }, { "getorderbook_MP", 0 }, { "getorderbook_MP", 1 }, { "gettradessince_MP", 0 }, @@ -117,9 +114,16 @@ static const CRPCConvertParam vRPCConvertParams[] = // omni_rpctx { "send_OMNI", 2 }, { "sendsto_OMNI", 1 }, + { "trade_MP", 1 }, // depreciated + { "trade_MP", 3 }, // depreciated + { "trade_MP", 5 }, // depreciated { "sendtrade_OMNI", 1 }, { "sendtrade_OMNI", 3 }, - { "sendtrade_OMNI", 5 }, + { "sendcanceltradesbyprice_OMNI", 1 }, + { "sendcanceltradesbyprice_OMNI", 3 }, + { "sendcanceltradesbypair_OMNI", 1 }, + { "sendcanceltradesbypair_OMNI", 2 }, + { "sendcancelalltrades_OMNI", 1 }, { "sendissuancefixed_OMNI", 1 }, { "sendissuancefixed_OMNI", 2 }, { "sendissuancefixed_OMNI", 3 }, diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index a7ae73bbd57d1..f1866a504711a 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -364,12 +364,16 @@ static const CRPCCommand vRPCCommands[] = { "omni layer", "getgrants_MP", &getgrants_MP, false, false, true }, { "omni layer", "getactivedexsells_MP", &getactivedexsells_MP, false, false, true }, { "omni layer", "getactivecrowdsales_MP", &getactivecrowdsales_MP, false, false, true }, - { "hidden", "trade_MP", &sendtrade_OMNI, false, false, true }, - { "hidden", "getorderbook_MP", &getorderbook_MP, false, false, true }, - { "hidden", "gettradessince_MP", &gettradessince_MP, false, false, true }, + { "omni layer", "getorderbook_MP", &getorderbook_MP, false, false, true }, + { "omni layer", "gettradessince_MP", &gettradessince_MP, false, false, true }, { "hidden", "getopenorders_MP", &getopenorders_MP, false, false, true }, - { "hidden", "gettradehistory_MP", &gettradehistory_MP, false, false, true }, - { "hidden", "gettrade_MP", &gettrade_MP, false, false, true }, + { "omni layer", "gettradehistory_MP", &gettradehistory_MP, false, false, true }, + { "omni layer", "gettrade_MP", &gettrade_MP, false, false, true }, + { "hidden", "trade_MP", &trade_MP, false, false, true }, // depreciated + { "omni layer", "sendtrade_OMNI", &sendtrade_OMNI, false, false, true }, + { "omni layer", "sendcanceltradesbyprice_OMNI", &sendcanceltradesbyprice_OMNI, false, false, true }, + { "omni layer", "sendcanceltradesbypair_OMNI", &sendcanceltradesbypair_OMNI, false, false, true }, + { "omni layer", "sendcancelalltrades_OMNI", &sendcancelalltrades_OMNI, false, false, true }, { "omni layer", "sendtoowners_MP", &sendsto_OMNI, false, false, true }, { "omni layer", "sendrawtx_MP", &sendrawtx_MP, false, false, true }, { "omni layer", "getsto_MP", &getsto_MP, false, false, true }, @@ -386,7 +390,6 @@ static const CRPCCommand vRPCCommands[] = { "omni layer", "sendgrant_OMNI", &sendgrant_OMNI, false, false, true }, { "omni layer", "sendrevoke_OMNI", &sendrevoke_OMNI, false, false, true }, { "omni layer", "sendclosecrowdsale_OMNI", &sendclosecrowdsale_OMNI, false, false, true }, - { "omni layer", "sendtrade_OMNI", &sendtrade_OMNI, false, false, true }, { "omni layer", "sendchangeissuer_OMNI", &sendchangeissuer_OMNI, false, false, true }, #endif // ENABLE_WALLET [required by Omni Core for now] }; diff --git a/src/rpcserver.h b/src/rpcserver.h index 438731532bcff..46622ca492e4d 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -240,7 +240,6 @@ extern json_spirit::Value getgrants_MP(const json_spirit::Array& params, bool fH extern json_spirit::Value getallbalancesforaddress_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getactivedexsells_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettransaction_MP(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value trade_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettrade_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getorderbook_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettradessince_MP(const json_spirit::Array& params, bool fHelp); @@ -263,8 +262,12 @@ extern json_spirit::Value sendsto_OMNI(const json_spirit::Array& params, bool fH extern json_spirit::Value sendgrant_OMNI(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value sendrevoke_OMNI(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value sendclosecrowdsale_OMNI(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendtrade_OMNI(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value sendchangeissuer_OMNI(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value trade_MP(const json_spirit::Array& params, bool fHelp); // depreciated +extern json_spirit::Value sendtrade_OMNI(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendcanceltradesbyprice_OMNI(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendcanceltradesbypair_OMNI(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendcancelalltrades_OMNI(const json_spirit::Array& params, bool fHelp); // in rest.cpp extern bool HTTPReq_REST(AcceptedConnection *conn,